All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/37] JZ4780 & CI20 support
@ 2015-04-21 14:46 ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips-6z/3iImG2C8G8FEW9MqTrA
  Cc: Paul Burton, Lars-Peter Clausen, Paul Cercueil, Thomas Gleixner,
	Jason Cooper, Mike Turquette, Greg Kroah-Hartman,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA

This series introduces initial support for the Ingenic JZ4780 SoC and
the Imagination Technologies MIPS Creator CI20 board which is built
around it. In the process the existing JZ4740 & qi_lb60 code gains
initial support for using DeviceTree such that much of the existing
platform code under arch/mips/jz4740 can be shared.

The series has undergone quite a bit of restructure since v2. Each
patch contains a changelog indicating its differences, but a rough
overview for changes across the series would be:

  - s/jz47xx/ingenic/ in various places, to reflect the fact that
    Ingenic have changed the naming scheme for their newest SoCs
    (now Mxxx).

  - Restructure the Kconfig entries to provide a MACH_INGENIC
    indicating and Ingenic SoC, and have boards select the
    appropriate SoC symbol.

  - Merge DT binding documentation where SoC bindings differ only
    by compatible strings.

  - Capitalise "JZ" in SoC names, where not identifiers in code,
    to match the way Ingenic write them.

  - Further clean up the Ingenic SoC interrupt controller driver
    and move it under drivers/irqchip/.

Review appreciated, and hopefully this can make it into v4.2.

Thanks,
    Paul

Paul Burton (37):
  devicetree/bindings: add Ingenic Semiconductor vendor prefix
  devicetree/bindings: add Qi Hardware vendor prefix
  MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
  MIPS: ingenic: add newer vendor IDs
  MIPS: JZ4740: require & include DT
  MIPS: irq_cpu: declare irqchip table entry
  MIPS: JZ4740: probe CPU interrupt controller via DT
  MIPS: JZ4740: use generic plat_irq_dispatch
  MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
  devicetree: document Ingenic SoC interrupt controller binding
  MIPS: JZ4740: probe interrupt controller via DT
  MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
  MIPS: JZ4740: register an irq_domain for the interrupt controller
  MIPS: JZ4740: drop intc debugfs code
  MIPS: JZ4740: remove jz_intc_base global
  MIPS: JZ4740: support >32 interrupts
  MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
  MIPS: JZ4740: read intc base address from DT
  MIPS: JZ4740: avoid JZ4740-specific naming
  MIPS: JZ4740: support newer SoC interrupt controllers
  irqchip: move Ingenic SoC intc driver to drivers/irqchip
  MIPS: JZ4740: call jz4740_clock_init earlier
  MIPS: JZ4740: replace use of jz4740_clock_bdata
  devicetree: add Ingenic CGU binding documentation
  clk: ingenic: add driver for Ingenic SoC CGU clocks
  MIPS,clk: migrate JZ4740 to common clock framework
  MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
  MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
  MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
  clk: ingenic: add JZ4780 CGU support
  MIPS: JZ4740: remove clock.h
  MIPS: JZ4740: only detect RAM size if not specified in DT
  devicetree: document Ingenic SoC UART binding
  serial: 8250_ingenic: support for Ingenic SoC UARTs
  MIPS: JZ4740: use Ingenic SoC UART driver
  MIPS: ingenic: initial JZ4780 support
  MIPS: ingenic: initial MIPS Creator CI20 support

 .../devicetree/bindings/clock/ingenic,cgu.txt      |  53 ++
 .../bindings/interrupt-controller/ingenic,intc.txt |  25 +
 .../devicetree/bindings/serial/ingenic,uart.txt    |  22 +
 .../devicetree/bindings/vendor-prefixes.txt        |   2 +
 arch/mips/Kconfig                                  |  11 +-
 arch/mips/boot/dts/Makefile                        |   1 +
 arch/mips/boot/dts/ingenic/Makefile                |  10 +
 arch/mips/boot/dts/ingenic/ci20.dts                |  21 +
 arch/mips/boot/dts/ingenic/jz4740.dtsi             |  68 ++
 arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++
 arch/mips/boot/dts/ingenic/qi_lb60.dts             |  15 +
 arch/mips/configs/ci20_defconfig                   | 169 ++++
 arch/mips/configs/qi_lb60_defconfig                |   3 +-
 arch/mips/include/asm/cpu-type.h                   |   2 +-
 arch/mips/include/asm/cpu.h                        |   6 +-
 arch/mips/include/asm/mach-jz4740/clock.h          |   3 +
 .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
 arch/mips/include/asm/mach-jz4740/irq.h            |  14 +-
 arch/mips/include/asm/mach-jz4740/platform.h       |   2 -
 arch/mips/jz4740/Kconfig                           |  17 +-
 arch/mips/jz4740/Makefile                          |   8 +-
 arch/mips/jz4740/Platform                          |   8 +-
 arch/mips/jz4740/board-qi_lb60.c                   |   7 -
 arch/mips/jz4740/clock-debugfs.c                   | 108 ---
 arch/mips/jz4740/clock.c                           | 924 ---------------------
 arch/mips/jz4740/clock.h                           |  76 --
 arch/mips/jz4740/gpio.c                            |   7 +-
 arch/mips/jz4740/irq.c                             | 162 ----
 arch/mips/jz4740/platform.c                        |  38 +-
 arch/mips/jz4740/pm.c                              |   2 -
 arch/mips/jz4740/prom.c                            |  13 -
 arch/mips/jz4740/reset.c                           |  13 +-
 arch/mips/jz4740/serial.c                          |  33 -
 arch/mips/jz4740/serial.h                          |  23 -
 arch/mips/jz4740/setup.c                           |  36 +-
 arch/mips/jz4740/time.c                            |  19 +-
 arch/mips/kernel/cpu-probe.c                       |   4 +-
 arch/mips/kernel/irq_cpu.c                         |   3 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/ingenic/Makefile                       |   3 +
 drivers/clk/ingenic/cgu.c                          | 711 ++++++++++++++++
 drivers/clk/ingenic/cgu.h                          | 223 +++++
 drivers/clk/ingenic/jz4740-cgu.c                   | 301 +++++++
 drivers/clk/ingenic/jz4780-cgu.c                   | 732 ++++++++++++++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-ingenic.c                      | 171 ++++
 drivers/tty/serial/8250/8250_ingenic.c             | 261 ++++++
 drivers/tty/serial/8250/Kconfig                    |   9 +
 drivers/tty/serial/8250/Makefile                   |   3 +
 include/dt-bindings/clock/jz4740-cgu.h             |  37 +
 include/dt-bindings/clock/jz4780-cgu.h             |  88 ++
 .../irq.h => include/linux/irqchip/ingenic.h       |   8 +-
 53 files changed, 3162 insertions(+), 1424 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
 create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
 create mode 100644 arch/mips/boot/dts/ingenic/Makefile
 create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
 create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
 create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi
 create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts
 create mode 100644 arch/mips/configs/ci20_defconfig
 delete mode 100644 arch/mips/jz4740/clock-debugfs.c
 delete mode 100644 arch/mips/jz4740/clock.c
 delete mode 100644 arch/mips/jz4740/clock.h
 delete mode 100644 arch/mips/jz4740/irq.c
 delete mode 100644 arch/mips/jz4740/serial.c
 delete mode 100644 arch/mips/jz4740/serial.h
 create mode 100644 drivers/clk/ingenic/Makefile
 create mode 100644 drivers/clk/ingenic/cgu.c
 create mode 100644 drivers/clk/ingenic/cgu.h
 create mode 100644 drivers/clk/ingenic/jz4740-cgu.c
 create mode 100644 drivers/clk/ingenic/jz4780-cgu.c
 create mode 100644 drivers/irqchip/irq-ingenic.c
 create mode 100644 drivers/tty/serial/8250/8250_ingenic.c
 create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
 create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
 rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (74%)

-- 
2.3.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 00/37] JZ4780 & CI20 support
@ 2015-04-21 14:46 ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Paul Burton, Lars-Peter Clausen, Paul Cercueil, Thomas Gleixner,
	Jason Cooper, Mike Turquette, Greg Kroah-Hartman, devicetree,
	linux-serial

This series introduces initial support for the Ingenic JZ4780 SoC and
the Imagination Technologies MIPS Creator CI20 board which is built
around it. In the process the existing JZ4740 & qi_lb60 code gains
initial support for using DeviceTree such that much of the existing
platform code under arch/mips/jz4740 can be shared.

The series has undergone quite a bit of restructure since v2. Each
patch contains a changelog indicating its differences, but a rough
overview for changes across the series would be:

  - s/jz47xx/ingenic/ in various places, to reflect the fact that
    Ingenic have changed the naming scheme for their newest SoCs
    (now Mxxx).

  - Restructure the Kconfig entries to provide a MACH_INGENIC
    indicating and Ingenic SoC, and have boards select the
    appropriate SoC symbol.

  - Merge DT binding documentation where SoC bindings differ only
    by compatible strings.

  - Capitalise "JZ" in SoC names, where not identifiers in code,
    to match the way Ingenic write them.

  - Further clean up the Ingenic SoC interrupt controller driver
    and move it under drivers/irqchip/.

Review appreciated, and hopefully this can make it into v4.2.

Thanks,
    Paul

Paul Burton (37):
  devicetree/bindings: add Ingenic Semiconductor vendor prefix
  devicetree/bindings: add Qi Hardware vendor prefix
  MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
  MIPS: ingenic: add newer vendor IDs
  MIPS: JZ4740: require & include DT
  MIPS: irq_cpu: declare irqchip table entry
  MIPS: JZ4740: probe CPU interrupt controller via DT
  MIPS: JZ4740: use generic plat_irq_dispatch
  MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
  devicetree: document Ingenic SoC interrupt controller binding
  MIPS: JZ4740: probe interrupt controller via DT
  MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
  MIPS: JZ4740: register an irq_domain for the interrupt controller
  MIPS: JZ4740: drop intc debugfs code
  MIPS: JZ4740: remove jz_intc_base global
  MIPS: JZ4740: support >32 interrupts
  MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
  MIPS: JZ4740: read intc base address from DT
  MIPS: JZ4740: avoid JZ4740-specific naming
  MIPS: JZ4740: support newer SoC interrupt controllers
  irqchip: move Ingenic SoC intc driver to drivers/irqchip
  MIPS: JZ4740: call jz4740_clock_init earlier
  MIPS: JZ4740: replace use of jz4740_clock_bdata
  devicetree: add Ingenic CGU binding documentation
  clk: ingenic: add driver for Ingenic SoC CGU clocks
  MIPS,clk: migrate JZ4740 to common clock framework
  MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
  MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
  MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
  clk: ingenic: add JZ4780 CGU support
  MIPS: JZ4740: remove clock.h
  MIPS: JZ4740: only detect RAM size if not specified in DT
  devicetree: document Ingenic SoC UART binding
  serial: 8250_ingenic: support for Ingenic SoC UARTs
  MIPS: JZ4740: use Ingenic SoC UART driver
  MIPS: ingenic: initial JZ4780 support
  MIPS: ingenic: initial MIPS Creator CI20 support

 .../devicetree/bindings/clock/ingenic,cgu.txt      |  53 ++
 .../bindings/interrupt-controller/ingenic,intc.txt |  25 +
 .../devicetree/bindings/serial/ingenic,uart.txt    |  22 +
 .../devicetree/bindings/vendor-prefixes.txt        |   2 +
 arch/mips/Kconfig                                  |  11 +-
 arch/mips/boot/dts/Makefile                        |   1 +
 arch/mips/boot/dts/ingenic/Makefile                |  10 +
 arch/mips/boot/dts/ingenic/ci20.dts                |  21 +
 arch/mips/boot/dts/ingenic/jz4740.dtsi             |  68 ++
 arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++
 arch/mips/boot/dts/ingenic/qi_lb60.dts             |  15 +
 arch/mips/configs/ci20_defconfig                   | 169 ++++
 arch/mips/configs/qi_lb60_defconfig                |   3 +-
 arch/mips/include/asm/cpu-type.h                   |   2 +-
 arch/mips/include/asm/cpu.h                        |   6 +-
 arch/mips/include/asm/mach-jz4740/clock.h          |   3 +
 .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
 arch/mips/include/asm/mach-jz4740/irq.h            |  14 +-
 arch/mips/include/asm/mach-jz4740/platform.h       |   2 -
 arch/mips/jz4740/Kconfig                           |  17 +-
 arch/mips/jz4740/Makefile                          |   8 +-
 arch/mips/jz4740/Platform                          |   8 +-
 arch/mips/jz4740/board-qi_lb60.c                   |   7 -
 arch/mips/jz4740/clock-debugfs.c                   | 108 ---
 arch/mips/jz4740/clock.c                           | 924 ---------------------
 arch/mips/jz4740/clock.h                           |  76 --
 arch/mips/jz4740/gpio.c                            |   7 +-
 arch/mips/jz4740/irq.c                             | 162 ----
 arch/mips/jz4740/platform.c                        |  38 +-
 arch/mips/jz4740/pm.c                              |   2 -
 arch/mips/jz4740/prom.c                            |  13 -
 arch/mips/jz4740/reset.c                           |  13 +-
 arch/mips/jz4740/serial.c                          |  33 -
 arch/mips/jz4740/serial.h                          |  23 -
 arch/mips/jz4740/setup.c                           |  36 +-
 arch/mips/jz4740/time.c                            |  19 +-
 arch/mips/kernel/cpu-probe.c                       |   4 +-
 arch/mips/kernel/irq_cpu.c                         |   3 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/ingenic/Makefile                       |   3 +
 drivers/clk/ingenic/cgu.c                          | 711 ++++++++++++++++
 drivers/clk/ingenic/cgu.h                          | 223 +++++
 drivers/clk/ingenic/jz4740-cgu.c                   | 301 +++++++
 drivers/clk/ingenic/jz4780-cgu.c                   | 732 ++++++++++++++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-ingenic.c                      | 171 ++++
 drivers/tty/serial/8250/8250_ingenic.c             | 261 ++++++
 drivers/tty/serial/8250/Kconfig                    |   9 +
 drivers/tty/serial/8250/Makefile                   |   3 +
 include/dt-bindings/clock/jz4740-cgu.h             |  37 +
 include/dt-bindings/clock/jz4780-cgu.h             |  88 ++
 .../irq.h => include/linux/irqchip/ingenic.h       |   8 +-
 53 files changed, 3162 insertions(+), 1424 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
 create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
 create mode 100644 arch/mips/boot/dts/ingenic/Makefile
 create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
 create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
 create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi
 create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts
 create mode 100644 arch/mips/configs/ci20_defconfig
 delete mode 100644 arch/mips/jz4740/clock-debugfs.c
 delete mode 100644 arch/mips/jz4740/clock.c
 delete mode 100644 arch/mips/jz4740/clock.h
 delete mode 100644 arch/mips/jz4740/irq.c
 delete mode 100644 arch/mips/jz4740/serial.c
 delete mode 100644 arch/mips/jz4740/serial.h
 create mode 100644 drivers/clk/ingenic/Makefile
 create mode 100644 drivers/clk/ingenic/cgu.c
 create mode 100644 drivers/clk/ingenic/cgu.h
 create mode 100644 drivers/clk/ingenic/jz4740-cgu.c
 create mode 100644 drivers/clk/ingenic/jz4780-cgu.c
 create mode 100644 drivers/irqchip/irq-ingenic.c
 create mode 100644 drivers/tty/serial/8250/8250_ingenic.c
 create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
 create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
 rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (74%)

-- 
2.3.5

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

* [PATCH v3 00/37] JZ4780 & CI20 support
@ 2015-04-21 14:46 ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips
  Cc: Paul Burton, Lars-Peter Clausen, Paul Cercueil, Thomas Gleixner,
	Jason Cooper, Mike Turquette, Greg Kroah-Hartman, devicetree,
	linux-serial

This series introduces initial support for the Ingenic JZ4780 SoC and
the Imagination Technologies MIPS Creator CI20 board which is built
around it. In the process the existing JZ4740 & qi_lb60 code gains
initial support for using DeviceTree such that much of the existing
platform code under arch/mips/jz4740 can be shared.

The series has undergone quite a bit of restructure since v2. Each
patch contains a changelog indicating its differences, but a rough
overview for changes across the series would be:

  - s/jz47xx/ingenic/ in various places, to reflect the fact that
    Ingenic have changed the naming scheme for their newest SoCs
    (now Mxxx).

  - Restructure the Kconfig entries to provide a MACH_INGENIC
    indicating and Ingenic SoC, and have boards select the
    appropriate SoC symbol.

  - Merge DT binding documentation where SoC bindings differ only
    by compatible strings.

  - Capitalise "JZ" in SoC names, where not identifiers in code,
    to match the way Ingenic write them.

  - Further clean up the Ingenic SoC interrupt controller driver
    and move it under drivers/irqchip/.

Review appreciated, and hopefully this can make it into v4.2.

Thanks,
    Paul

Paul Burton (37):
  devicetree/bindings: add Ingenic Semiconductor vendor prefix
  devicetree/bindings: add Qi Hardware vendor prefix
  MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
  MIPS: ingenic: add newer vendor IDs
  MIPS: JZ4740: require & include DT
  MIPS: irq_cpu: declare irqchip table entry
  MIPS: JZ4740: probe CPU interrupt controller via DT
  MIPS: JZ4740: use generic plat_irq_dispatch
  MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
  devicetree: document Ingenic SoC interrupt controller binding
  MIPS: JZ4740: probe interrupt controller via DT
  MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
  MIPS: JZ4740: register an irq_domain for the interrupt controller
  MIPS: JZ4740: drop intc debugfs code
  MIPS: JZ4740: remove jz_intc_base global
  MIPS: JZ4740: support >32 interrupts
  MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
  MIPS: JZ4740: read intc base address from DT
  MIPS: JZ4740: avoid JZ4740-specific naming
  MIPS: JZ4740: support newer SoC interrupt controllers
  irqchip: move Ingenic SoC intc driver to drivers/irqchip
  MIPS: JZ4740: call jz4740_clock_init earlier
  MIPS: JZ4740: replace use of jz4740_clock_bdata
  devicetree: add Ingenic CGU binding documentation
  clk: ingenic: add driver for Ingenic SoC CGU clocks
  MIPS,clk: migrate JZ4740 to common clock framework
  MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
  MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
  MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
  clk: ingenic: add JZ4780 CGU support
  MIPS: JZ4740: remove clock.h
  MIPS: JZ4740: only detect RAM size if not specified in DT
  devicetree: document Ingenic SoC UART binding
  serial: 8250_ingenic: support for Ingenic SoC UARTs
  MIPS: JZ4740: use Ingenic SoC UART driver
  MIPS: ingenic: initial JZ4780 support
  MIPS: ingenic: initial MIPS Creator CI20 support

 .../devicetree/bindings/clock/ingenic,cgu.txt      |  53 ++
 .../bindings/interrupt-controller/ingenic,intc.txt |  25 +
 .../devicetree/bindings/serial/ingenic,uart.txt    |  22 +
 .../devicetree/bindings/vendor-prefixes.txt        |   2 +
 arch/mips/Kconfig                                  |  11 +-
 arch/mips/boot/dts/Makefile                        |   1 +
 arch/mips/boot/dts/ingenic/Makefile                |  10 +
 arch/mips/boot/dts/ingenic/ci20.dts                |  21 +
 arch/mips/boot/dts/ingenic/jz4740.dtsi             |  68 ++
 arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++
 arch/mips/boot/dts/ingenic/qi_lb60.dts             |  15 +
 arch/mips/configs/ci20_defconfig                   | 169 ++++
 arch/mips/configs/qi_lb60_defconfig                |   3 +-
 arch/mips/include/asm/cpu-type.h                   |   2 +-
 arch/mips/include/asm/cpu.h                        |   6 +-
 arch/mips/include/asm/mach-jz4740/clock.h          |   3 +
 .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
 arch/mips/include/asm/mach-jz4740/irq.h            |  14 +-
 arch/mips/include/asm/mach-jz4740/platform.h       |   2 -
 arch/mips/jz4740/Kconfig                           |  17 +-
 arch/mips/jz4740/Makefile                          |   8 +-
 arch/mips/jz4740/Platform                          |   8 +-
 arch/mips/jz4740/board-qi_lb60.c                   |   7 -
 arch/mips/jz4740/clock-debugfs.c                   | 108 ---
 arch/mips/jz4740/clock.c                           | 924 ---------------------
 arch/mips/jz4740/clock.h                           |  76 --
 arch/mips/jz4740/gpio.c                            |   7 +-
 arch/mips/jz4740/irq.c                             | 162 ----
 arch/mips/jz4740/platform.c                        |  38 +-
 arch/mips/jz4740/pm.c                              |   2 -
 arch/mips/jz4740/prom.c                            |  13 -
 arch/mips/jz4740/reset.c                           |  13 +-
 arch/mips/jz4740/serial.c                          |  33 -
 arch/mips/jz4740/serial.h                          |  23 -
 arch/mips/jz4740/setup.c                           |  36 +-
 arch/mips/jz4740/time.c                            |  19 +-
 arch/mips/kernel/cpu-probe.c                       |   4 +-
 arch/mips/kernel/irq_cpu.c                         |   3 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/ingenic/Makefile                       |   3 +
 drivers/clk/ingenic/cgu.c                          | 711 ++++++++++++++++
 drivers/clk/ingenic/cgu.h                          | 223 +++++
 drivers/clk/ingenic/jz4740-cgu.c                   | 301 +++++++
 drivers/clk/ingenic/jz4780-cgu.c                   | 732 ++++++++++++++++
 drivers/irqchip/Kconfig                            |   5 +
 drivers/irqchip/Makefile                           |   1 +
 drivers/irqchip/irq-ingenic.c                      | 171 ++++
 drivers/tty/serial/8250/8250_ingenic.c             | 261 ++++++
 drivers/tty/serial/8250/Kconfig                    |   9 +
 drivers/tty/serial/8250/Makefile                   |   3 +
 include/dt-bindings/clock/jz4740-cgu.h             |  37 +
 include/dt-bindings/clock/jz4780-cgu.h             |  88 ++
 .../irq.h => include/linux/irqchip/ingenic.h       |   8 +-
 53 files changed, 3162 insertions(+), 1424 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
 create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
 create mode 100644 arch/mips/boot/dts/ingenic/Makefile
 create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
 create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
 create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi
 create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts
 create mode 100644 arch/mips/configs/ci20_defconfig
 delete mode 100644 arch/mips/jz4740/clock-debugfs.c
 delete mode 100644 arch/mips/jz4740/clock.c
 delete mode 100644 arch/mips/jz4740/clock.h
 delete mode 100644 arch/mips/jz4740/irq.c
 delete mode 100644 arch/mips/jz4740/serial.c
 delete mode 100644 arch/mips/jz4740/serial.h
 create mode 100644 drivers/clk/ingenic/Makefile
 create mode 100644 drivers/clk/ingenic/cgu.c
 create mode 100644 drivers/clk/ingenic/cgu.h
 create mode 100644 drivers/clk/ingenic/jz4740-cgu.c
 create mode 100644 drivers/clk/ingenic/jz4780-cgu.c
 create mode 100644 drivers/irqchip/irq-ingenic.c
 create mode 100644 drivers/tty/serial/8250/8250_ingenic.c
 create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
 create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
 rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (74%)

-- 
2.3.5

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

* [PATCH v3 01/37] devicetree/bindings: add Ingenic Semiconductor vendor prefix
  2015-04-21 14:46 ` Paul Burton
  (?)
@ 2015-04-21 14:46     ` Paul Burton
  -1 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips-6z/3iImG2C8G8FEW9MqTrA
  Cc: Paul Burton, Lars-Peter Clausen, devicetree-u79uwXL29TY76Z2rM5mHXA

Define a vendor prefix for Ingenic Semiconductor, a vendor of MIPS-based
SoCs. Simply use 'ingenic'.

Signed-off-by: Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
Cc: Lars-Peter Clausen <lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index c0e55db..721b14e 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -100,6 +100,7 @@ ibm	International Business Machines (IBM)
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
+ingenic	Ingenic Semiconductor
 innolux	Innolux Corporation
 intel	Intel Corporation
 intercontrol	Inter Control Group
-- 
2.3.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 01/37] devicetree/bindings: add Ingenic Semiconductor vendor prefix
@ 2015-04-21 14:46     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, devicetree

Define a vendor prefix for Ingenic Semiconductor, a vendor of MIPS-based
SoCs. Simply use 'ingenic'.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index c0e55db..721b14e 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -100,6 +100,7 @@ ibm	International Business Machines (IBM)
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
+ingenic	Ingenic Semiconductor
 innolux	Innolux Corporation
 intel	Intel Corporation
 intercontrol	Inter Control Group
-- 
2.3.5

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

* [PATCH v3 01/37] devicetree/bindings: add Ingenic Semiconductor vendor prefix
@ 2015-04-21 14:46     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, devicetree

Define a vendor prefix for Ingenic Semiconductor, a vendor of MIPS-based
SoCs. Simply use 'ingenic'.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index c0e55db..721b14e 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -100,6 +100,7 @@ ibm	International Business Machines (IBM)
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
+ingenic	Ingenic Semiconductor
 innolux	Innolux Corporation
 intel	Intel Corporation
 intercontrol	Inter Control Group
-- 
2.3.5

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

* [PATCH v3 02/37] devicetree/bindings: add Qi Hardware vendor prefix
  2015-04-21 14:46 ` Paul Burton
  (?)
@ 2015-04-21 14:46     ` Paul Burton
  -1 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips-6z/3iImG2C8G8FEW9MqTrA
  Cc: Paul Burton, Lars-Peter Clausen, devicetree-u79uwXL29TY76Z2rM5mHXA

Define a vendor prefix for Qi Hardware, creators of the Ben Nanonote
(qi_lb60) among other open devices.

Signed-off-by: Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
Cc: Lars-Peter Clausen <lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
Changes in v3:
  - New patch.
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 721b14e..5aa0bd8 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -155,6 +155,7 @@ powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
 qcom	Qualcomm Technologies, Inc
 qemu	QEMU, a generic and open source machine emulator and virtualizer
+qi	Qi Hardware
 qnap	QNAP Systems, Inc.
 radxa	Radxa
 raidsonic	RaidSonic Technology GmbH
-- 
2.3.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 02/37] devicetree/bindings: add Qi Hardware vendor prefix
@ 2015-04-21 14:46     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, devicetree

Define a vendor prefix for Qi Hardware, creators of the Ben Nanonote
(qi_lb60) among other open devices.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - New patch.
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 721b14e..5aa0bd8 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -155,6 +155,7 @@ powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
 qcom	Qualcomm Technologies, Inc
 qemu	QEMU, a generic and open source machine emulator and virtualizer
+qi	Qi Hardware
 qnap	QNAP Systems, Inc.
 radxa	Radxa
 raidsonic	RaidSonic Technology GmbH
-- 
2.3.5

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

* [PATCH v3 02/37] devicetree/bindings: add Qi Hardware vendor prefix
@ 2015-04-21 14:46     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, devicetree

Define a vendor prefix for Qi Hardware, creators of the Ben Nanonote
(qi_lb60) among other open devices.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - New patch.
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 721b14e..5aa0bd8 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -155,6 +155,7 @@ powervr	PowerVR (deprecated, use img)
 qca	Qualcomm Atheros, Inc.
 qcom	Qualcomm Technologies, Inc
 qemu	QEMU, a generic and open source machine emulator and virtualizer
+qi	Qi Hardware
 qnap	QNAP Systems, Inc.
 radxa	Radxa
 raidsonic	RaidSonic Technology GmbH
-- 
2.3.5

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

* [PATCH v3 03/37] MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

In preparation for supporting Ingenic SoCs other than the JZ4740,
introduce MACH_INGENIC to Kconfig & move MACH_JZ4740 to a separate
entry selected by the board when appropriate. This allows MACH_INGENIC
to be used to enable things generic across Ingenic SoCs.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - New patch.
---
 arch/mips/Kconfig                   | 5 ++---
 arch/mips/configs/qi_lb60_defconfig | 2 +-
 arch/mips/jz4740/Kconfig            | 7 ++++++-
 arch/mips/jz4740/Platform           | 8 ++++----
 4 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f501665..4a3acca 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -288,9 +288,8 @@ config MACH_JAZZ
 	 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and
 	 Olivetti M700-10 workstations.
 
-config MACH_JZ4740
-	bool "Ingenic JZ4740 based machines"
-	select SYS_HAS_CPU_MIPS32_R1
+config MACH_INGENIC
+	bool "Ingenic SoC based machines"
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_ZBOOT_UART16550
diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig
index 2b96547..1139b89 100644
--- a/arch/mips/configs/qi_lb60_defconfig
+++ b/arch/mips/configs/qi_lb60_defconfig
@@ -1,4 +1,4 @@
-CONFIG_MACH_JZ4740=y
+CONFIG_MACH_INGENIC=y
 # CONFIG_COMPACTION is not set
 # CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_HZ_100=y
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 4689030..dff0966 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -1,9 +1,14 @@
 choice
 	prompt "Machine type"
-	depends on MACH_JZ4740
+	depends on MACH_INGENIC
 	default JZ4740_QI_LB60
 
 config JZ4740_QI_LB60
 	bool "Qi Hardware Ben NanoNote"
+	select MACH_JZ4740
 
 endchoice
+
+config MACH_JZ4740
+	bool
+	select SYS_HAS_CPU_MIPS32_R1
diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform
index c41d300..28448d3 100644
--- a/arch/mips/jz4740/Platform
+++ b/arch/mips/jz4740/Platform
@@ -1,4 +1,4 @@
-platform-$(CONFIG_MACH_JZ4740)	+= jz4740/
-cflags-$(CONFIG_MACH_JZ4740)	+= -I$(srctree)/arch/mips/include/asm/mach-jz4740
-load-$(CONFIG_MACH_JZ4740)	+= 0xffffffff80010000
-zload-$(CONFIG_MACH_JZ4740)	+= 0xffffffff80600000
+platform-$(CONFIG_MACH_INGENIC)	+= jz4740/
+cflags-$(CONFIG_MACH_INGENIC)	+= -I$(srctree)/arch/mips/include/asm/mach-jz4740
+load-$(CONFIG_MACH_INGENIC)	+= 0xffffffff80010000
+zload-$(CONFIG_MACH_INGENIC)	+= 0xffffffff80600000
-- 
2.3.5

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

* [PATCH v3 03/37] MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

In preparation for supporting Ingenic SoCs other than the JZ4740,
introduce MACH_INGENIC to Kconfig & move MACH_JZ4740 to a separate
entry selected by the board when appropriate. This allows MACH_INGENIC
to be used to enable things generic across Ingenic SoCs.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - New patch.
---
 arch/mips/Kconfig                   | 5 ++---
 arch/mips/configs/qi_lb60_defconfig | 2 +-
 arch/mips/jz4740/Kconfig            | 7 ++++++-
 arch/mips/jz4740/Platform           | 8 ++++----
 4 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f501665..4a3acca 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -288,9 +288,8 @@ config MACH_JAZZ
 	 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and
 	 Olivetti M700-10 workstations.
 
-config MACH_JZ4740
-	bool "Ingenic JZ4740 based machines"
-	select SYS_HAS_CPU_MIPS32_R1
+config MACH_INGENIC
+	bool "Ingenic SoC based machines"
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_ZBOOT_UART16550
diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig
index 2b96547..1139b89 100644
--- a/arch/mips/configs/qi_lb60_defconfig
+++ b/arch/mips/configs/qi_lb60_defconfig
@@ -1,4 +1,4 @@
-CONFIG_MACH_JZ4740=y
+CONFIG_MACH_INGENIC=y
 # CONFIG_COMPACTION is not set
 # CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_HZ_100=y
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 4689030..dff0966 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -1,9 +1,14 @@
 choice
 	prompt "Machine type"
-	depends on MACH_JZ4740
+	depends on MACH_INGENIC
 	default JZ4740_QI_LB60
 
 config JZ4740_QI_LB60
 	bool "Qi Hardware Ben NanoNote"
+	select MACH_JZ4740
 
 endchoice
+
+config MACH_JZ4740
+	bool
+	select SYS_HAS_CPU_MIPS32_R1
diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform
index c41d300..28448d3 100644
--- a/arch/mips/jz4740/Platform
+++ b/arch/mips/jz4740/Platform
@@ -1,4 +1,4 @@
-platform-$(CONFIG_MACH_JZ4740)	+= jz4740/
-cflags-$(CONFIG_MACH_JZ4740)	+= -I$(srctree)/arch/mips/include/asm/mach-jz4740
-load-$(CONFIG_MACH_JZ4740)	+= 0xffffffff80010000
-zload-$(CONFIG_MACH_JZ4740)	+= 0xffffffff80600000
+platform-$(CONFIG_MACH_INGENIC)	+= jz4740/
+cflags-$(CONFIG_MACH_INGENIC)	+= -I$(srctree)/arch/mips/include/asm/mach-jz4740
+load-$(CONFIG_MACH_INGENIC)	+= 0xffffffff80010000
+zload-$(CONFIG_MACH_INGENIC)	+= 0xffffffff80600000
-- 
2.3.5

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

* [PATCH v3 04/37] MIPS: ingenic: add newer vendor IDs
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Ingenic have actually varied the vendor/company ID of the XBurst cores
across their range of SoCs, whilst keeping the product ID & revision
constant... Add definitions for vendor IDs known to be used in some of
Ingenic's newer SoCs, and handle them in the same way as the existing
Ingenic vendor ID from the JZ4740.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Co-authored-by: Paul Cercueil <paul@crapouillou.net>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - New patch, encompassing patch 31 "MIPS: add jz4780 Ingenic vendor
    ID" of v2.

  - Give up on associating vendor IDs with unique SoCs.
---
 arch/mips/include/asm/cpu.h  | 6 ++++--
 arch/mips/kernel/cpu-probe.c | 4 +++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index e3adca1..73dd357 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -42,7 +42,9 @@
 #define PRID_COMP_LEXRA		0x0b0000
 #define PRID_COMP_NETLOGIC	0x0c0000
 #define PRID_COMP_CAVIUM	0x0d0000
-#define PRID_COMP_INGENIC	0xd00000
+#define PRID_COMP_INGENIC_D0	0xd00000	/* JZ4740, JZ4750 */
+#define PRID_COMP_INGENIC_D1	0xd10000	/* JZ4770, JZ4775 */
+#define PRID_COMP_INGENIC_E1	0xe10000	/* JZ4780 */
 
 /*
  * Assigned Processor ID (implementation) values for bits 15:8 of the PRId
@@ -168,7 +170,7 @@
 #define PRID_IMP_CAVIUM_CN70XX 0x9600
 
 /*
- * These are the PRID's for when 23:16 == PRID_COMP_INGENIC
+ * These are the PRID's for when 23:16 == PRID_COMP_INGENIC_*
  */
 
 #define PRID_IMP_JZRISC	       0x0200
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index e36515d..0444e69 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1444,7 +1444,9 @@ void cpu_probe(void)
 	case PRID_COMP_CAVIUM:
 		cpu_probe_cavium(c, cpu);
 		break;
-	case PRID_COMP_INGENIC:
+	case PRID_COMP_INGENIC_D0:
+	case PRID_COMP_INGENIC_D1:
+	case PRID_COMP_INGENIC_E1:
 		cpu_probe_ingenic(c, cpu);
 		break;
 	case PRID_COMP_NETLOGIC:
-- 
2.3.5

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

* [PATCH v3 04/37] MIPS: ingenic: add newer vendor IDs
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Ingenic have actually varied the vendor/company ID of the XBurst cores
across their range of SoCs, whilst keeping the product ID & revision
constant... Add definitions for vendor IDs known to be used in some of
Ingenic's newer SoCs, and handle them in the same way as the existing
Ingenic vendor ID from the JZ4740.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Co-authored-by: Paul Cercueil <paul@crapouillou.net>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - New patch, encompassing patch 31 "MIPS: add jz4780 Ingenic vendor
    ID" of v2.

  - Give up on associating vendor IDs with unique SoCs.
---
 arch/mips/include/asm/cpu.h  | 6 ++++--
 arch/mips/kernel/cpu-probe.c | 4 +++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index e3adca1..73dd357 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -42,7 +42,9 @@
 #define PRID_COMP_LEXRA		0x0b0000
 #define PRID_COMP_NETLOGIC	0x0c0000
 #define PRID_COMP_CAVIUM	0x0d0000
-#define PRID_COMP_INGENIC	0xd00000
+#define PRID_COMP_INGENIC_D0	0xd00000	/* JZ4740, JZ4750 */
+#define PRID_COMP_INGENIC_D1	0xd10000	/* JZ4770, JZ4775 */
+#define PRID_COMP_INGENIC_E1	0xe10000	/* JZ4780 */
 
 /*
  * Assigned Processor ID (implementation) values for bits 15:8 of the PRId
@@ -168,7 +170,7 @@
 #define PRID_IMP_CAVIUM_CN70XX 0x9600
 
 /*
- * These are the PRID's for when 23:16 == PRID_COMP_INGENIC
+ * These are the PRID's for when 23:16 == PRID_COMP_INGENIC_*
  */
 
 #define PRID_IMP_JZRISC	       0x0200
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index e36515d..0444e69 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1444,7 +1444,9 @@ void cpu_probe(void)
 	case PRID_COMP_CAVIUM:
 		cpu_probe_cavium(c, cpu);
 		break;
-	case PRID_COMP_INGENIC:
+	case PRID_COMP_INGENIC_D0:
+	case PRID_COMP_INGENIC_D1:
+	case PRID_COMP_INGENIC_E1:
 		cpu_probe_ingenic(c, cpu);
 		break;
 	case PRID_COMP_NETLOGIC:
-- 
2.3.5

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

* [PATCH v3 05/37] MIPS: JZ4740: require & include DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Require a DT for JZ4740 based systems, and add a stub one for the
qi_lb60 (Ben NanoNote) board. Devices will be migrated to being probed
via this DT over time.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/Kconfig                      |  2 ++
 arch/mips/boot/dts/Makefile            |  1 +
 arch/mips/boot/dts/ingenic/Makefile    |  9 +++++++++
 arch/mips/boot/dts/ingenic/jz4740.dtsi |  5 +++++
 arch/mips/boot/dts/ingenic/qi_lb60.dts |  7 +++++++
 arch/mips/jz4740/setup.c               | 19 +++++++++++++++++++
 6 files changed, 43 insertions(+)
 create mode 100644 arch/mips/boot/dts/ingenic/Makefile
 create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
 create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4a3acca..741e364 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -299,6 +299,8 @@ config MACH_INGENIC
 	select SYS_HAS_EARLY_PRINTK
 	select HAVE_CLK
 	select GENERIC_IRQ_CHIP
+	select BUILTIN_DTB
+	select USE_OF
 
 config LANTIQ
 	bool "Lantiq based platforms"
diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile
index 5d95e4b..9c31b30 100644
--- a/arch/mips/boot/dts/Makefile
+++ b/arch/mips/boot/dts/Makefile
@@ -1,5 +1,6 @@
 dts-dirs	+= brcm
 dts-dirs	+= cavium-octeon
+dts-dirs	+= ingenic
 dts-dirs	+= lantiq
 dts-dirs	+= mti
 dts-dirs	+= netlogic
diff --git a/arch/mips/boot/dts/ingenic/Makefile b/arch/mips/boot/dts/ingenic/Makefile
new file mode 100644
index 0000000..0c84f0b
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/Makefile
@@ -0,0 +1,9 @@
+dtb-$(CONFIG_JZ4740_QI_LB60)	+= qi_lb60.dtb
+
+obj-y				+= $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+
+# Force kbuild to make empty built-in.o if necessary
+obj-				+= dummy.o
+
+always				:= $(dtb-y)
+clean-files			:= *.dtb *.dtb.S
diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
new file mode 100644
index 0000000..c538691f
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -0,0 +1,5 @@
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "ingenic,jz4740";
+};
diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts
new file mode 100644
index 0000000..0c0f639
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+#include "jz4740.dtsi"
+
+/ {
+	compatible = "qi,lb60", "ingenic,jz4740";
+};
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index ef796f9..d6bb7a3 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -17,8 +17,11 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
 
 #include <asm/bootinfo.h>
+#include <asm/prom.h>
 
 #include <asm/mach-jz4740/base.h>
 
@@ -53,8 +56,24 @@ void __init plat_mem_setup(void)
 {
 	jz4740_reset_init();
 	jz4740_detect_mem();
+	__dt_setup_arch(__dtb_start);
 }
 
+void __init device_tree_init(void)
+{
+	if (!initial_boot_params)
+		return;
+
+	unflatten_and_copy_device_tree();
+}
+
+static int __init populate_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	return 0;
+}
+arch_initcall(populate_machine);
+
 const char *get_system_type(void)
 {
 	return "JZ4740";
-- 
2.3.5

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

* [PATCH v3 05/37] MIPS: JZ4740: require & include DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Require a DT for JZ4740 based systems, and add a stub one for the
qi_lb60 (Ben NanoNote) board. Devices will be migrated to being probed
via this DT over time.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/Kconfig                      |  2 ++
 arch/mips/boot/dts/Makefile            |  1 +
 arch/mips/boot/dts/ingenic/Makefile    |  9 +++++++++
 arch/mips/boot/dts/ingenic/jz4740.dtsi |  5 +++++
 arch/mips/boot/dts/ingenic/qi_lb60.dts |  7 +++++++
 arch/mips/jz4740/setup.c               | 19 +++++++++++++++++++
 6 files changed, 43 insertions(+)
 create mode 100644 arch/mips/boot/dts/ingenic/Makefile
 create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
 create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 4a3acca..741e364 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -299,6 +299,8 @@ config MACH_INGENIC
 	select SYS_HAS_EARLY_PRINTK
 	select HAVE_CLK
 	select GENERIC_IRQ_CHIP
+	select BUILTIN_DTB
+	select USE_OF
 
 config LANTIQ
 	bool "Lantiq based platforms"
diff --git a/arch/mips/boot/dts/Makefile b/arch/mips/boot/dts/Makefile
index 5d95e4b..9c31b30 100644
--- a/arch/mips/boot/dts/Makefile
+++ b/arch/mips/boot/dts/Makefile
@@ -1,5 +1,6 @@
 dts-dirs	+= brcm
 dts-dirs	+= cavium-octeon
+dts-dirs	+= ingenic
 dts-dirs	+= lantiq
 dts-dirs	+= mti
 dts-dirs	+= netlogic
diff --git a/arch/mips/boot/dts/ingenic/Makefile b/arch/mips/boot/dts/ingenic/Makefile
new file mode 100644
index 0000000..0c84f0b
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/Makefile
@@ -0,0 +1,9 @@
+dtb-$(CONFIG_JZ4740_QI_LB60)	+= qi_lb60.dtb
+
+obj-y				+= $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+
+# Force kbuild to make empty built-in.o if necessary
+obj-				+= dummy.o
+
+always				:= $(dtb-y)
+clean-files			:= *.dtb *.dtb.S
diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
new file mode 100644
index 0000000..c538691f
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -0,0 +1,5 @@
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "ingenic,jz4740";
+};
diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts
new file mode 100644
index 0000000..0c0f639
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+#include "jz4740.dtsi"
+
+/ {
+	compatible = "qi,lb60", "ingenic,jz4740";
+};
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index ef796f9..d6bb7a3 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -17,8 +17,11 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
 
 #include <asm/bootinfo.h>
+#include <asm/prom.h>
 
 #include <asm/mach-jz4740/base.h>
 
@@ -53,8 +56,24 @@ void __init plat_mem_setup(void)
 {
 	jz4740_reset_init();
 	jz4740_detect_mem();
+	__dt_setup_arch(__dtb_start);
 }
 
+void __init device_tree_init(void)
+{
+	if (!initial_boot_params)
+		return;
+
+	unflatten_and_copy_device_tree();
+}
+
+static int __init populate_machine(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	return 0;
+}
+arch_initcall(populate_machine);
+
 const char *get_system_type(void)
 {
 	return "JZ4740";
-- 
2.3.5

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

* [PATCH v3 06/37] MIPS: irq_cpu: declare irqchip table entry
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Allow the MIPS CPU interrupt controller to be probed from DT using the
generic __irqchip_of_table for platforms which use irqchip_init. This
will avoid such platforms needing to duplicate the compatible string &
init function pointer.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/kernel/irq_cpu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 6eb7a3f..f96313d 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -38,6 +38,8 @@
 #include <asm/mipsmtregs.h>
 #include <asm/setup.h>
 
+#include "../../drivers/irqchip/irqchip.h"
+
 static inline void unmask_mips_irq(struct irq_data *d)
 {
 	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
@@ -167,3 +169,4 @@ int __init mips_cpu_irq_of_init(struct device_node *of_node,
 	__mips_cpu_irq_init(of_node);
 	return 0;
 }
+IRQCHIP_DECLARE(cpu_intc, "mti,cpu-interrupt-controller", mips_cpu_irq_of_init);
-- 
2.3.5

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

* [PATCH v3 06/37] MIPS: irq_cpu: declare irqchip table entry
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Allow the MIPS CPU interrupt controller to be probed from DT using the
generic __irqchip_of_table for platforms which use irqchip_init. This
will avoid such platforms needing to duplicate the compatible string &
init function pointer.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/kernel/irq_cpu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c
index 6eb7a3f..f96313d 100644
--- a/arch/mips/kernel/irq_cpu.c
+++ b/arch/mips/kernel/irq_cpu.c
@@ -38,6 +38,8 @@
 #include <asm/mipsmtregs.h>
 #include <asm/setup.h>
 
+#include "../../drivers/irqchip/irqchip.h"
+
 static inline void unmask_mips_irq(struct irq_data *d)
 {
 	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
@@ -167,3 +169,4 @@ int __init mips_cpu_irq_of_init(struct device_node *of_node,
 	__mips_cpu_irq_init(of_node);
 	return 0;
 }
+IRQCHIP_DECLARE(cpu_intc, "mti,cpu-interrupt-controller", mips_cpu_irq_of_init);
-- 
2.3.5

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

* [PATCH v3 07/37] MIPS: JZ4740: probe CPU interrupt controller via DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Use the generic irqchip_init function to probe irqchip drivers using DT,
and add the appropriate node to the JZ4740 devicetree in place of the
call to mips_cpu_irq_init.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/boot/dts/ingenic/jz4740.dtsi | 7 +++++++
 arch/mips/jz4740/irq.c                 | 4 ++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index c538691f..2d64765c 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -2,4 +2,11 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 	compatible = "ingenic,jz4740";
+
+	cpuintc: cpuintc@0 {
+		#address-cells = <0>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		compatible = "mti,cpu-interrupt-controller";
+	};
 };
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 97206b3..3ec90875 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/irqchip.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -27,7 +28,6 @@
 
 #include <asm/io.h>
 #include <asm/mipsregs.h>
-#include <asm/irq_cpu.h>
 
 #include <asm/mach-jz4740/base.h>
 #include <asm/mach-jz4740/irq.h>
@@ -84,7 +84,7 @@ void __init arch_init_irq(void)
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 
-	mips_cpu_irq_init();
+	irqchip_init();
 
 	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
-- 
2.3.5

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

* [PATCH v3 07/37] MIPS: JZ4740: probe CPU interrupt controller via DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Use the generic irqchip_init function to probe irqchip drivers using DT,
and add the appropriate node to the JZ4740 devicetree in place of the
call to mips_cpu_irq_init.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/boot/dts/ingenic/jz4740.dtsi | 7 +++++++
 arch/mips/jz4740/irq.c                 | 4 ++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index c538691f..2d64765c 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -2,4 +2,11 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 	compatible = "ingenic,jz4740";
+
+	cpuintc: cpuintc@0 {
+		#address-cells = <0>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		compatible = "mti,cpu-interrupt-controller";
+	};
 };
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 97206b3..3ec90875 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/irqchip.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -27,7 +28,6 @@
 
 #include <asm/io.h>
 #include <asm/mipsregs.h>
-#include <asm/irq_cpu.h>
 
 #include <asm/mach-jz4740/base.h>
 #include <asm/mach-jz4740/irq.h>
@@ -84,7 +84,7 @@ void __init arch_init_irq(void)
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 
-	mips_cpu_irq_init();
+	irqchip_init();
 
 	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
-- 
2.3.5

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

* [PATCH v3 08/37] MIPS: JZ4740: use generic plat_irq_dispatch
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Make use of the generic plat_irq_dispatch function introduced by commit
85f7cdacbb81 "MIPS: Provide a generic plat_irq_dispatch", in order to
reduce unnecessary code duplication.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/irq.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 3ec90875..a2452bb 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -27,7 +27,6 @@
 #include <linux/seq_file.h>
 
 #include <asm/io.h>
-#include <asm/mipsregs.h>
 
 #include <asm/mach-jz4740/base.h>
 #include <asm/mach-jz4740/irq.h>
@@ -111,17 +110,6 @@ void __init arch_init_irq(void)
 	setup_irq(2, &jz4740_cascade_action);
 }
 
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-	if (pending & STATUSF_IP2)
-		do_IRQ(2);
-	else if (pending & STATUSF_IP3)
-		do_IRQ(3);
-	else
-		spurious_interrupt();
-}
-
 #ifdef CONFIG_DEBUG_FS
 
 static inline void intc_seq_reg(struct seq_file *s, const char *name,
-- 
2.3.5

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

* [PATCH v3 08/37] MIPS: JZ4740: use generic plat_irq_dispatch
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Make use of the generic plat_irq_dispatch function introduced by commit
85f7cdacbb81 "MIPS: Provide a generic plat_irq_dispatch", in order to
reduce unnecessary code duplication.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/irq.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 3ec90875..a2452bb 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -27,7 +27,6 @@
 #include <linux/seq_file.h>
 
 #include <asm/io.h>
-#include <asm/mipsregs.h>
 
 #include <asm/mach-jz4740/base.h>
 #include <asm/mach-jz4740/irq.h>
@@ -111,17 +110,6 @@ void __init arch_init_irq(void)
 	setup_irq(2, &jz4740_cascade_action);
 }
 
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-	if (pending & STATUSF_IP2)
-		do_IRQ(2);
-	else if (pending & STATUSF_IP3)
-		do_IRQ(3);
-	else
-		spurious_interrupt();
-}
-
 #ifdef CONFIG_DEBUG_FS
 
 static inline void intc_seq_reg(struct seq_file *s, const char *name,
-- 
2.3.5

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

* [PATCH v3 09/37] MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

In preparation for moving the JZ4740 interrupt controller driver to
drivers/irqchip, move arch_init_irq into setup.c such that everything
remaining in irq.c is related to said JZ4740 interrupt controller.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/irq.h | 2 ++
 arch/mips/jz4740/irq.c                  | 5 +----
 arch/mips/jz4740/setup.c                | 8 ++++++++
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
index df50736..5ce4302 100644
--- a/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -54,4 +54,6 @@
 
 #define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6)
 
+extern void __init jz4740_intc_init(void);
+
 #endif
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index a2452bb..bac1f52 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/irqchip.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -78,13 +77,11 @@ static struct irqaction jz4740_cascade_action = {
 	.name = "JZ4740 cascade interrupt",
 };
 
-void __init arch_init_irq(void)
+void __init jz4740_intc_init(void)
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 
-	irqchip_init();
-
 	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
 	/* Mask all irqs */
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index d6bb7a3..4808730 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/irqchip.h>
 #include <linux/kernel.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
@@ -24,6 +25,7 @@
 #include <asm/prom.h>
 
 #include <asm/mach-jz4740/base.h>
+#include <asm/mach-jz4740/irq.h>
 
 #include "reset.h"
 
@@ -78,3 +80,9 @@ const char *get_system_type(void)
 {
 	return "JZ4740";
 }
+
+void __init arch_init_irq(void)
+{
+	irqchip_init();
+	jz4740_intc_init();
+}
-- 
2.3.5

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

* [PATCH v3 09/37] MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

In preparation for moving the JZ4740 interrupt controller driver to
drivers/irqchip, move arch_init_irq into setup.c such that everything
remaining in irq.c is related to said JZ4740 interrupt controller.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/irq.h | 2 ++
 arch/mips/jz4740/irq.c                  | 5 +----
 arch/mips/jz4740/setup.c                | 8 ++++++++
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
index df50736..5ce4302 100644
--- a/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -54,4 +54,6 @@
 
 #define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6)
 
+extern void __init jz4740_intc_init(void);
+
 #endif
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index a2452bb..bac1f52 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -18,7 +18,6 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/irqchip.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -78,13 +77,11 @@ static struct irqaction jz4740_cascade_action = {
 	.name = "JZ4740 cascade interrupt",
 };
 
-void __init arch_init_irq(void)
+void __init jz4740_intc_init(void)
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 
-	irqchip_init();
-
 	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
 	/* Mask all irqs */
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index d6bb7a3..4808730 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -16,6 +16,7 @@
 
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/irqchip.h>
 #include <linux/kernel.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
@@ -24,6 +25,7 @@
 #include <asm/prom.h>
 
 #include <asm/mach-jz4740/base.h>
+#include <asm/mach-jz4740/irq.h>
 
 #include "reset.h"
 
@@ -78,3 +80,9 @@ const char *get_system_type(void)
 {
 	return "JZ4740";
 }
+
+void __init arch_init_irq(void)
+{
+	irqchip_init();
+	jz4740_intc_init();
+}
-- 
2.3.5

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

* [PATCH v3 10/37] devicetree: document Ingenic SoC interrupt controller binding
  2015-04-21 14:46 ` Paul Burton
  (?)
@ 2015-04-21 14:46     ` Paul Burton
  -1 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips-6z/3iImG2C8G8FEW9MqTrA
  Cc: Paul Burton, Lars-Peter Clausen, devicetree-u79uwXL29TY76Z2rM5mHXA

Add binding documentation for Ingenic SoC interrupt controllers.

Signed-off-by: Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
Cc: Lars-Peter Clausen <lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
Changes in v3:
  - Merge documentation for various Ingenic SoCs, which only differ by
    their compatible strings.

Changes in v2:
  - None.
---
 .../bindings/interrupt-controller/ingenic,intc.txt | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
new file mode 100644
index 0000000..5d652e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
@@ -0,0 +1,25 @@
+Ingenic SoC Interrupt Controller
+
+Required properties:
+
+- compatible : should be "ingenic,<socname>-intc". For example
+  "ingenic,jz4740-intc" or "ingenic,jz4780-intc".
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+- interrupt-parent : phandle of the CPU interrupt controller.
+- interrupts : Specifies the CPU interrupt the controller is connected to.
+
+Example:
+
+intc: intc@10001000 {
+	compatible = "ingenic,jz4740-intc";
+	reg = <0x10001000 0x14>;
+
+	interrupt-controller;
+	#interrupt-cells = <1>;
+
+	interrupt-parent = <&cpuintc>;
+	interrupts = <2>;
+};
-- 
2.3.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 10/37] devicetree: document Ingenic SoC interrupt controller binding
@ 2015-04-21 14:46     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, devicetree

Add binding documentation for Ingenic SoC interrupt controllers.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - Merge documentation for various Ingenic SoCs, which only differ by
    their compatible strings.

Changes in v2:
  - None.
---
 .../bindings/interrupt-controller/ingenic,intc.txt | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
new file mode 100644
index 0000000..5d652e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
@@ -0,0 +1,25 @@
+Ingenic SoC Interrupt Controller
+
+Required properties:
+
+- compatible : should be "ingenic,<socname>-intc". For example
+  "ingenic,jz4740-intc" or "ingenic,jz4780-intc".
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+- interrupt-parent : phandle of the CPU interrupt controller.
+- interrupts : Specifies the CPU interrupt the controller is connected to.
+
+Example:
+
+intc: intc@10001000 {
+	compatible = "ingenic,jz4740-intc";
+	reg = <0x10001000 0x14>;
+
+	interrupt-controller;
+	#interrupt-cells = <1>;
+
+	interrupt-parent = <&cpuintc>;
+	interrupts = <2>;
+};
-- 
2.3.5

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

* [PATCH v3 10/37] devicetree: document Ingenic SoC interrupt controller binding
@ 2015-04-21 14:46     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, devicetree

Add binding documentation for Ingenic SoC interrupt controllers.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - Merge documentation for various Ingenic SoCs, which only differ by
    their compatible strings.

Changes in v2:
  - None.
---
 .../bindings/interrupt-controller/ingenic,intc.txt | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
new file mode 100644
index 0000000..5d652e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
@@ -0,0 +1,25 @@
+Ingenic SoC Interrupt Controller
+
+Required properties:
+
+- compatible : should be "ingenic,<socname>-intc". For example
+  "ingenic,jz4740-intc" or "ingenic,jz4780-intc".
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+- interrupt-parent : phandle of the CPU interrupt controller.
+- interrupts : Specifies the CPU interrupt the controller is connected to.
+
+Example:
+
+intc: intc@10001000 {
+	compatible = "ingenic,jz4740-intc";
+	reg = <0x10001000 0x14>;
+
+	interrupt-controller;
+	#interrupt-cells = <1>;
+
+	interrupt-parent = <&cpuintc>;
+	interrupts = <2>;
+};
-- 
2.3.5

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

* [PATCH v3 11/37] MIPS: JZ4740: probe interrupt controller via DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Declare the JZ4740 interrupt controller for probe via DT using the
standard irqchip_init function, and make use of that function to probe
the controller by adding the appropriate node to the JZ4740 dtsi.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch, merging patches 8 through 10 of v2 & dropping the addition
    of temporary code removed a couple of patches later.
---
 arch/mips/boot/dts/ingenic/jz4740.dtsi  | 11 +++++++++++
 arch/mips/include/asm/mach-jz4740/irq.h |  2 --
 arch/mips/jz4740/irq.c                  |  8 +++++++-
 arch/mips/jz4740/setup.c                |  2 --
 4 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index 2d64765c..3841024 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -9,4 +9,15 @@
 		interrupt-controller;
 		compatible = "mti,cpu-interrupt-controller";
 	};
+
+	intc: intc@10001000 {
+		compatible = "ingenic,jz4740-intc";
+		reg = <0x10001000 0x14>;
+
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		interrupt-parent = <&cpuintc>;
+		interrupts = <2>;
+	};
 };
diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
index 5ce4302..df50736 100644
--- a/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -54,6 +54,4 @@
 
 #define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6)
 
-extern void __init jz4740_intc_init(void);
-
 #endif
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index bac1f52..43e000a 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/of_irq.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -32,6 +33,8 @@
 
 #include "irq.h"
 
+#include "../../drivers/irqchip/irqchip.h"
+
 static void __iomem *jz_intc_base;
 
 #define JZ_REG_INTC_STATUS	0x00
@@ -77,7 +80,8 @@ static struct irqaction jz4740_cascade_action = {
 	.name = "JZ4740 cascade interrupt",
 };
 
-void __init jz4740_intc_init(void)
+static int __init jz4740_intc_of_init(struct device_node *node,
+	struct device_node *parent)
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
@@ -105,7 +109,9 @@ void __init jz4740_intc_init(void)
 	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
 	setup_irq(2, &jz4740_cascade_action);
+	return 0;
 }
+IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
 
 #ifdef CONFIG_DEBUG_FS
 
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 4808730..8c08d7d 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -25,7 +25,6 @@
 #include <asm/prom.h>
 
 #include <asm/mach-jz4740/base.h>
-#include <asm/mach-jz4740/irq.h>
 
 #include "reset.h"
 
@@ -84,5 +83,4 @@ const char *get_system_type(void)
 void __init arch_init_irq(void)
 {
 	irqchip_init();
-	jz4740_intc_init();
 }
-- 
2.3.5

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

* [PATCH v3 11/37] MIPS: JZ4740: probe interrupt controller via DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Declare the JZ4740 interrupt controller for probe via DT using the
standard irqchip_init function, and make use of that function to probe
the controller by adding the appropriate node to the JZ4740 dtsi.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch, merging patches 8 through 10 of v2 & dropping the addition
    of temporary code removed a couple of patches later.
---
 arch/mips/boot/dts/ingenic/jz4740.dtsi  | 11 +++++++++++
 arch/mips/include/asm/mach-jz4740/irq.h |  2 --
 arch/mips/jz4740/irq.c                  |  8 +++++++-
 arch/mips/jz4740/setup.c                |  2 --
 4 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index 2d64765c..3841024 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -9,4 +9,15 @@
 		interrupt-controller;
 		compatible = "mti,cpu-interrupt-controller";
 	};
+
+	intc: intc@10001000 {
+		compatible = "ingenic,jz4740-intc";
+		reg = <0x10001000 0x14>;
+
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		interrupt-parent = <&cpuintc>;
+		interrupts = <2>;
+	};
 };
diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
index 5ce4302..df50736 100644
--- a/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -54,6 +54,4 @@
 
 #define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6)
 
-extern void __init jz4740_intc_init(void);
-
 #endif
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index bac1f52..43e000a 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/of_irq.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -32,6 +33,8 @@
 
 #include "irq.h"
 
+#include "../../drivers/irqchip/irqchip.h"
+
 static void __iomem *jz_intc_base;
 
 #define JZ_REG_INTC_STATUS	0x00
@@ -77,7 +80,8 @@ static struct irqaction jz4740_cascade_action = {
 	.name = "JZ4740 cascade interrupt",
 };
 
-void __init jz4740_intc_init(void)
+static int __init jz4740_intc_of_init(struct device_node *node,
+	struct device_node *parent)
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
@@ -105,7 +109,9 @@ void __init jz4740_intc_init(void)
 	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
 	setup_irq(2, &jz4740_cascade_action);
+	return 0;
 }
+IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
 
 #ifdef CONFIG_DEBUG_FS
 
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 4808730..8c08d7d 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -25,7 +25,6 @@
 #include <asm/prom.h>
 
 #include <asm/mach-jz4740/base.h>
-#include <asm/mach-jz4740/irq.h>
 
 #include "reset.h"
 
@@ -84,5 +83,4 @@ const char *get_system_type(void)
 void __init arch_init_irq(void)
 {
 	irqchip_init();
-	jz4740_intc_init();
 }
-- 
2.3.5

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

* [PATCH v3 12/37] MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Rather than hardcoding the IRQ number used to cascade interrupts from
the SoC interrupt controller to the CPU interrupt controller, read that
IRQ number from the DT describing the system.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/irq.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 43e000a..ed51915 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -85,6 +85,11 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
+	int parent_irq;
+
+	parent_irq = irq_of_parse_and_map(node, 0);
+	if (!parent_irq)
+		return -EINVAL;
 
 	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
@@ -108,7 +113,7 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 
 	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
-	setup_irq(2, &jz4740_cascade_action);
+	setup_irq(parent_irq, &jz4740_cascade_action);
 	return 0;
 }
 IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
-- 
2.3.5

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

* [PATCH v3 12/37] MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Rather than hardcoding the IRQ number used to cascade interrupts from
the SoC interrupt controller to the CPU interrupt controller, read that
IRQ number from the DT describing the system.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/irq.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 43e000a..ed51915 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -85,6 +85,11 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
+	int parent_irq;
+
+	parent_irq = irq_of_parse_and_map(node, 0);
+	if (!parent_irq)
+		return -EINVAL;
 
 	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
@@ -108,7 +113,7 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 
 	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
-	setup_irq(2, &jz4740_cascade_action);
+	setup_irq(parent_irq, &jz4740_cascade_action);
 	return 0;
 }
 IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
-- 
2.3.5

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

* [PATCH v3 13/37] MIPS: JZ4740: register an irq_domain for the interrupt controller
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

When probining the interrupt controller, register an IRQ domain such
that the interrupts can be translated by devicetree code & thus used
from devicetree.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/irq.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index ed51915..ddcf78a 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -85,6 +85,7 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
+	struct irq_domain *domain;
 	int parent_irq;
 
 	parent_irq = irq_of_parse_and_map(node, 0);
@@ -113,6 +114,11 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 
 	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
+	domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0,
+				       &irq_domain_simple_ops, NULL);
+	if (!domain)
+		pr_warn("unable to register IRQ domain\n");
+
 	setup_irq(parent_irq, &jz4740_cascade_action);
 	return 0;
 }
-- 
2.3.5

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

* [PATCH v3 13/37] MIPS: JZ4740: register an irq_domain for the interrupt controller
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

When probining the interrupt controller, register an IRQ domain such
that the interrupts can be translated by devicetree code & thus used
from devicetree.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/irq.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index ed51915..ddcf78a 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -85,6 +85,7 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
+	struct irq_domain *domain;
 	int parent_irq;
 
 	parent_irq = irq_of_parse_and_map(node, 0);
@@ -113,6 +114,11 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 
 	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
 
+	domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0,
+				       &irq_domain_simple_ops, NULL);
+	if (!domain)
+		pr_warn("unable to register IRQ domain\n");
+
 	setup_irq(parent_irq, &jz4740_cascade_action);
 	return 0;
 }
-- 
2.3.5

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

* [PATCH v3 14/37] MIPS: JZ4740: drop intc debugfs code
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

The debugfs code becomes a nuisance when attempting to avoid globals,
since the interrupt controller probe function run too early for it to be
safe to create the debugfs files. Drop it.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
I recognise this one may be controversial. Please shout if you care
about this debugfs code!

Changes in v3:
  - New patch.
---
 arch/mips/jz4740/irq.c | 42 ------------------------------------------
 1 file changed, 42 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index ddcf78a..615eaa8 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -23,9 +23,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
 #include <asm/io.h>
 
 #include <asm/mach-jz4740/base.h>
@@ -123,42 +120,3 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 	return 0;
 }
 IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
-
-#ifdef CONFIG_DEBUG_FS
-
-static inline void intc_seq_reg(struct seq_file *s, const char *name,
-	unsigned int reg)
-{
-	seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg));
-}
-
-static int intc_regs_show(struct seq_file *s, void *unused)
-{
-	intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS);
-	intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK);
-	intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING);
-
-	return 0;
-}
-
-static int intc_regs_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, intc_regs_show, NULL);
-}
-
-static const struct file_operations intc_regs_operations = {
-	.open		= intc_regs_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init intc_debugfs_init(void)
-{
-	(void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO,
-				NULL, NULL, &intc_regs_operations);
-	return 0;
-}
-subsys_initcall(intc_debugfs_init);
-
-#endif
-- 
2.3.5

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

* [PATCH v3 14/37] MIPS: JZ4740: drop intc debugfs code
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

The debugfs code becomes a nuisance when attempting to avoid globals,
since the interrupt controller probe function run too early for it to be
safe to create the debugfs files. Drop it.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
I recognise this one may be controversial. Please shout if you care
about this debugfs code!

Changes in v3:
  - New patch.
---
 arch/mips/jz4740/irq.c | 42 ------------------------------------------
 1 file changed, 42 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index ddcf78a..615eaa8 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -23,9 +23,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
 #include <asm/io.h>
 
 #include <asm/mach-jz4740/base.h>
@@ -123,42 +120,3 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 	return 0;
 }
 IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
-
-#ifdef CONFIG_DEBUG_FS
-
-static inline void intc_seq_reg(struct seq_file *s, const char *name,
-	unsigned int reg)
-{
-	seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg));
-}
-
-static int intc_regs_show(struct seq_file *s, void *unused)
-{
-	intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS);
-	intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK);
-	intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING);
-
-	return 0;
-}
-
-static int intc_regs_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, intc_regs_show, NULL);
-}
-
-static const struct file_operations intc_regs_operations = {
-	.open		= intc_regs_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init intc_debugfs_init(void)
-{
-	(void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO,
-				NULL, NULL, &intc_regs_operations);
-	return 0;
-}
-subsys_initcall(intc_debugfs_init);
-
-#endif
-- 
2.3.5

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

* [PATCH v3 15/37] MIPS: JZ4740: remove jz_intc_base global
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Avoid the need for the global variable jz_intc_base by introducing a
struct ingenic_intc_data and passing it around as the IRQ handler data.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/irq.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 615eaa8..498ff28 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -32,7 +32,9 @@
 
 #include "../../drivers/irqchip/irqchip.h"
 
-static void __iomem *jz_intc_base;
+struct ingenic_intc_data {
+	void __iomem *base;
+};
 
 #define JZ_REG_INTC_STATUS	0x00
 #define JZ_REG_INTC_MASK	0x04
@@ -42,9 +44,10 @@ static void __iomem *jz_intc_base;
 
 static irqreturn_t jz4740_cascade(int irq, void *data)
 {
+	struct ingenic_intc_data *intc = irq_get_handler_data(irq);
 	uint32_t irq_reg;
 
-	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
+	irq_reg = readl(intc->base + JZ_REG_INTC_PENDING);
 
 	if (irq_reg)
 		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
@@ -80,21 +83,30 @@ static struct irqaction jz4740_cascade_action = {
 static int __init jz4740_intc_of_init(struct device_node *node,
 	struct device_node *parent)
 {
+	struct ingenic_intc_data *intc;
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 	struct irq_domain *domain;
-	int parent_irq;
+	int parent_irq, err = 0;
+
+	intc = kzalloc(sizeof(*intc), GFP_KERNEL);
+	if (!intc) {
+		err = -ENOMEM;
+		goto out;
+	}
 
 	parent_irq = irq_of_parse_and_map(node, 0);
-	if (!parent_irq)
-		return -EINVAL;
+	if (!parent_irq) {
+		err = -EINVAL;
+		goto out;
+	}
 
-	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
+	intc->base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
 	/* Mask all irqs */
-	writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
+	writel(0xffffffff, intc->base + JZ_REG_INTC_SET_MASK);
 
-	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base,
+	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, intc->base,
 		handle_level_irq);
 
 	gc->wake_enabled = IRQ_MSK(32);
@@ -116,7 +128,12 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 	if (!domain)
 		pr_warn("unable to register IRQ domain\n");
 
+	err = irq_set_handler_data(parent_irq, intc);
+	if (err)
+		goto out;
+
 	setup_irq(parent_irq, &jz4740_cascade_action);
-	return 0;
+out:
+	return err;
 }
 IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
-- 
2.3.5

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

* [PATCH v3 15/37] MIPS: JZ4740: remove jz_intc_base global
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Avoid the need for the global variable jz_intc_base by introducing a
struct ingenic_intc_data and passing it around as the IRQ handler data.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/irq.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 615eaa8..498ff28 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -32,7 +32,9 @@
 
 #include "../../drivers/irqchip/irqchip.h"
 
-static void __iomem *jz_intc_base;
+struct ingenic_intc_data {
+	void __iomem *base;
+};
 
 #define JZ_REG_INTC_STATUS	0x00
 #define JZ_REG_INTC_MASK	0x04
@@ -42,9 +44,10 @@ static void __iomem *jz_intc_base;
 
 static irqreturn_t jz4740_cascade(int irq, void *data)
 {
+	struct ingenic_intc_data *intc = irq_get_handler_data(irq);
 	uint32_t irq_reg;
 
-	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
+	irq_reg = readl(intc->base + JZ_REG_INTC_PENDING);
 
 	if (irq_reg)
 		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
@@ -80,21 +83,30 @@ static struct irqaction jz4740_cascade_action = {
 static int __init jz4740_intc_of_init(struct device_node *node,
 	struct device_node *parent)
 {
+	struct ingenic_intc_data *intc;
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 	struct irq_domain *domain;
-	int parent_irq;
+	int parent_irq, err = 0;
+
+	intc = kzalloc(sizeof(*intc), GFP_KERNEL);
+	if (!intc) {
+		err = -ENOMEM;
+		goto out;
+	}
 
 	parent_irq = irq_of_parse_and_map(node, 0);
-	if (!parent_irq)
-		return -EINVAL;
+	if (!parent_irq) {
+		err = -EINVAL;
+		goto out;
+	}
 
-	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
+	intc->base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
 	/* Mask all irqs */
-	writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
+	writel(0xffffffff, intc->base + JZ_REG_INTC_SET_MASK);
 
-	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base,
+	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, intc->base,
 		handle_level_irq);
 
 	gc->wake_enabled = IRQ_MSK(32);
@@ -116,7 +128,12 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 	if (!domain)
 		pr_warn("unable to register IRQ domain\n");
 
+	err = irq_set_handler_data(parent_irq, intc);
+	if (err)
+		goto out;
+
 	setup_irq(parent_irq, &jz4740_cascade_action);
-	return 0;
+out:
+	return err;
 }
 IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
-- 
2.3.5

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

* [PATCH v3 16/37] MIPS: JZ4740: support >32 interrupts
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

On newer Ingenic SoCs the interrupt controller supports more than 32
interrupts, which it does by duplicating the registers at intervals
of 0x20 bytes within its address space. Add support for an arbitrary
number of interrupts using multiple generic chips, and provide the
number of chips to register from the interrupt controller probe
function.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - Name probe functions a little more generically, ie. "1chip" rather
    than "jz4740". This is more for consistency with the later "2chip"
    variant that is used across a number of SoCs.

Changes in v2:
  - None.
---
 arch/mips/jz4740/irq.c | 71 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 46 insertions(+), 25 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 498ff28..a154d9b 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -34,6 +34,7 @@
 
 struct ingenic_intc_data {
 	void __iomem *base;
+	unsigned num_chips;
 };
 
 #define JZ_REG_INTC_STATUS	0x00
@@ -41,16 +42,22 @@ struct ingenic_intc_data {
 #define JZ_REG_INTC_SET_MASK	0x08
 #define JZ_REG_INTC_CLEAR_MASK	0x0c
 #define JZ_REG_INTC_PENDING	0x10
+#define CHIP_SIZE		0x20
 
 static irqreturn_t jz4740_cascade(int irq, void *data)
 {
 	struct ingenic_intc_data *intc = irq_get_handler_data(irq);
 	uint32_t irq_reg;
+	unsigned i;
 
-	irq_reg = readl(intc->base + JZ_REG_INTC_PENDING);
+	for (i = 0; i < intc->num_chips; i++) {
+		irq_reg = readl(intc->base + (i * CHIP_SIZE) +
+				JZ_REG_INTC_PENDING);
+		if (!irq_reg)
+			continue;
 
-	if (irq_reg)
-		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
+		generic_handle_irq(__fls(irq_reg) + (i * 32) + JZ4740_IRQ_BASE);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -80,14 +87,15 @@ static struct irqaction jz4740_cascade_action = {
 	.name = "JZ4740 cascade interrupt",
 };
 
-static int __init jz4740_intc_of_init(struct device_node *node,
-	struct device_node *parent)
+static int __init ingenic_intc_of_init(struct device_node *node,
+				       unsigned num_chips)
 {
 	struct ingenic_intc_data *intc;
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 	struct irq_domain *domain;
 	int parent_irq, err = 0;
+	unsigned i;
 
 	intc = kzalloc(sizeof(*intc), GFP_KERNEL);
 	if (!intc) {
@@ -101,27 +109,34 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 		goto out;
 	}
 
+	intc->num_chips = num_chips;
 	intc->base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
-	/* Mask all irqs */
-	writel(0xffffffff, intc->base + JZ_REG_INTC_SET_MASK);
-
-	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, intc->base,
-		handle_level_irq);
-
-	gc->wake_enabled = IRQ_MSK(32);
-
-	ct = gc->chip_types;
-	ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
-	ct->regs.disable = JZ_REG_INTC_SET_MASK;
-	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
-	ct->chip.irq_mask = irq_gc_mask_disable_reg;
-	ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
-	ct->chip.irq_set_wake = irq_gc_set_wake;
-	ct->chip.irq_suspend = jz4740_irq_suspend;
-	ct->chip.irq_resume = jz4740_irq_resume;
-
-	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
+	for (i = 0; i < num_chips; i++) {
+		/* Mask all irqs */
+		writel(0xffffffff, intc->base + (i * CHIP_SIZE) +
+		       JZ_REG_INTC_SET_MASK);
+
+		gc = irq_alloc_generic_chip("INTC", 1,
+					    JZ4740_IRQ_BASE + (i * 32),
+					    intc->base + (i * CHIP_SIZE),
+					    handle_level_irq);
+
+		gc->wake_enabled = IRQ_MSK(32);
+
+		ct = gc->chip_types;
+		ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
+		ct->regs.disable = JZ_REG_INTC_SET_MASK;
+		ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+		ct->chip.irq_mask = irq_gc_mask_disable_reg;
+		ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
+		ct->chip.irq_set_wake = irq_gc_set_wake;
+		ct->chip.irq_suspend = jz4740_irq_suspend;
+		ct->chip.irq_resume = jz4740_irq_resume;
+
+		irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0,
+				       IRQ_NOPROBE | IRQ_LEVEL);
+	}
 
 	domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0,
 				       &irq_domain_simple_ops, NULL);
@@ -136,4 +151,10 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 out:
 	return err;
 }
-IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
+
+static int __init intc_1chip_of_init(struct device_node *node,
+				     struct device_node *parent)
+{
+	return ingenic_intc_of_init(node, 1);
+}
+IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init);
-- 
2.3.5

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

* [PATCH v3 16/37] MIPS: JZ4740: support >32 interrupts
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

On newer Ingenic SoCs the interrupt controller supports more than 32
interrupts, which it does by duplicating the registers at intervals
of 0x20 bytes within its address space. Add support for an arbitrary
number of interrupts using multiple generic chips, and provide the
number of chips to register from the interrupt controller probe
function.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - Name probe functions a little more generically, ie. "1chip" rather
    than "jz4740". This is more for consistency with the later "2chip"
    variant that is used across a number of SoCs.

Changes in v2:
  - None.
---
 arch/mips/jz4740/irq.c | 71 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 46 insertions(+), 25 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 498ff28..a154d9b 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -34,6 +34,7 @@
 
 struct ingenic_intc_data {
 	void __iomem *base;
+	unsigned num_chips;
 };
 
 #define JZ_REG_INTC_STATUS	0x00
@@ -41,16 +42,22 @@ struct ingenic_intc_data {
 #define JZ_REG_INTC_SET_MASK	0x08
 #define JZ_REG_INTC_CLEAR_MASK	0x0c
 #define JZ_REG_INTC_PENDING	0x10
+#define CHIP_SIZE		0x20
 
 static irqreturn_t jz4740_cascade(int irq, void *data)
 {
 	struct ingenic_intc_data *intc = irq_get_handler_data(irq);
 	uint32_t irq_reg;
+	unsigned i;
 
-	irq_reg = readl(intc->base + JZ_REG_INTC_PENDING);
+	for (i = 0; i < intc->num_chips; i++) {
+		irq_reg = readl(intc->base + (i * CHIP_SIZE) +
+				JZ_REG_INTC_PENDING);
+		if (!irq_reg)
+			continue;
 
-	if (irq_reg)
-		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
+		generic_handle_irq(__fls(irq_reg) + (i * 32) + JZ4740_IRQ_BASE);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -80,14 +87,15 @@ static struct irqaction jz4740_cascade_action = {
 	.name = "JZ4740 cascade interrupt",
 };
 
-static int __init jz4740_intc_of_init(struct device_node *node,
-	struct device_node *parent)
+static int __init ingenic_intc_of_init(struct device_node *node,
+				       unsigned num_chips)
 {
 	struct ingenic_intc_data *intc;
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 	struct irq_domain *domain;
 	int parent_irq, err = 0;
+	unsigned i;
 
 	intc = kzalloc(sizeof(*intc), GFP_KERNEL);
 	if (!intc) {
@@ -101,27 +109,34 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 		goto out;
 	}
 
+	intc->num_chips = num_chips;
 	intc->base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
-	/* Mask all irqs */
-	writel(0xffffffff, intc->base + JZ_REG_INTC_SET_MASK);
-
-	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, intc->base,
-		handle_level_irq);
-
-	gc->wake_enabled = IRQ_MSK(32);
-
-	ct = gc->chip_types;
-	ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
-	ct->regs.disable = JZ_REG_INTC_SET_MASK;
-	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
-	ct->chip.irq_mask = irq_gc_mask_disable_reg;
-	ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
-	ct->chip.irq_set_wake = irq_gc_set_wake;
-	ct->chip.irq_suspend = jz4740_irq_suspend;
-	ct->chip.irq_resume = jz4740_irq_resume;
-
-	irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0, IRQ_NOPROBE | IRQ_LEVEL);
+	for (i = 0; i < num_chips; i++) {
+		/* Mask all irqs */
+		writel(0xffffffff, intc->base + (i * CHIP_SIZE) +
+		       JZ_REG_INTC_SET_MASK);
+
+		gc = irq_alloc_generic_chip("INTC", 1,
+					    JZ4740_IRQ_BASE + (i * 32),
+					    intc->base + (i * CHIP_SIZE),
+					    handle_level_irq);
+
+		gc->wake_enabled = IRQ_MSK(32);
+
+		ct = gc->chip_types;
+		ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
+		ct->regs.disable = JZ_REG_INTC_SET_MASK;
+		ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+		ct->chip.irq_mask = irq_gc_mask_disable_reg;
+		ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
+		ct->chip.irq_set_wake = irq_gc_set_wake;
+		ct->chip.irq_suspend = jz4740_irq_suspend;
+		ct->chip.irq_resume = jz4740_irq_resume;
+
+		irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0,
+				       IRQ_NOPROBE | IRQ_LEVEL);
+	}
 
 	domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0,
 				       &irq_domain_simple_ops, NULL);
@@ -136,4 +151,10 @@ static int __init jz4740_intc_of_init(struct device_node *node,
 out:
 	return err;
 }
-IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
+
+static int __init intc_1chip_of_init(struct device_node *node,
+				     struct device_node *parent)
+{
+	return ingenic_intc_of_init(node, 1);
+}
+IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init);
-- 
2.3.5

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

* [PATCH v3 17/37] MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

For interrupts numbered after those of the interrupt controller, define
their numbers based upon the number of interrupts provided by the SoC
interrupt controller. This is in preparation for supporting newer
Ingenic SoCs which provide more interrupts.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/irq.h | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
index df50736..b218f76 100644
--- a/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -19,6 +19,10 @@
 #define MIPS_CPU_IRQ_BASE 0
 #define JZ4740_IRQ_BASE 8
 
+#ifdef CONFIG_MACH_JZ4740
+# define NR_INTC_IRQS	32
+#endif
+
 /* 1st-level interrupts */
 #define JZ4740_IRQ(x)		(JZ4740_IRQ_BASE + (x))
 #define JZ4740_IRQ_I2C		JZ4740_IRQ(1)
@@ -45,12 +49,12 @@
 #define JZ4740_IRQ_LCD		JZ4740_IRQ(30)
 
 /* 2nd-level interrupts */
-#define JZ4740_IRQ_DMA(x)	(JZ4740_IRQ(32) + (x))
+#define JZ4740_IRQ_DMA(x)	(JZ4740_IRQ(NR_INTC_IRQS) + (x))
 
 #define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x))
-#define JZ4740_IRQ_GPIO(x)	(JZ4740_IRQ(48) + (x))
+#define JZ4740_IRQ_GPIO(x)	(JZ4740_IRQ(NR_INTC_IRQS + 16) + (x))
 
-#define JZ4740_IRQ_ADC_BASE	JZ4740_IRQ(176)
+#define JZ4740_IRQ_ADC_BASE	JZ4740_IRQ(NR_INTC_IRQS + 144)
 
 #define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6)
 
-- 
2.3.5

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

* [PATCH v3 17/37] MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

For interrupts numbered after those of the interrupt controller, define
their numbers based upon the number of interrupts provided by the SoC
interrupt controller. This is in preparation for supporting newer
Ingenic SoCs which provide more interrupts.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/irq.h | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
index df50736..b218f76 100644
--- a/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -19,6 +19,10 @@
 #define MIPS_CPU_IRQ_BASE 0
 #define JZ4740_IRQ_BASE 8
 
+#ifdef CONFIG_MACH_JZ4740
+# define NR_INTC_IRQS	32
+#endif
+
 /* 1st-level interrupts */
 #define JZ4740_IRQ(x)		(JZ4740_IRQ_BASE + (x))
 #define JZ4740_IRQ_I2C		JZ4740_IRQ(1)
@@ -45,12 +49,12 @@
 #define JZ4740_IRQ_LCD		JZ4740_IRQ(30)
 
 /* 2nd-level interrupts */
-#define JZ4740_IRQ_DMA(x)	(JZ4740_IRQ(32) + (x))
+#define JZ4740_IRQ_DMA(x)	(JZ4740_IRQ(NR_INTC_IRQS) + (x))
 
 #define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x))
-#define JZ4740_IRQ_GPIO(x)	(JZ4740_IRQ(48) + (x))
+#define JZ4740_IRQ_GPIO(x)	(JZ4740_IRQ(NR_INTC_IRQS + 16) + (x))
 
-#define JZ4740_IRQ_ADC_BASE	JZ4740_IRQ(176)
+#define JZ4740_IRQ_ADC_BASE	JZ4740_IRQ(NR_INTC_IRQS + 144)
 
 #define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6)
 
-- 
2.3.5

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

* [PATCH v3 18/37] MIPS: JZ4740: read intc base address from DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Read the base address of the SoC interrupt controller from the device
tree rather than relying upon the JZ4740_INTC_BASE_ADDR macro, in order
to remove the dependency on the asm/mach-jz4740/base.h header.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/irq.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index a154d9b..58fe64f 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -18,14 +18,13 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 
 #include <asm/io.h>
-
-#include <asm/mach-jz4740/base.h>
 #include <asm/mach-jz4740/irq.h>
 
 #include "irq.h"
@@ -110,7 +109,11 @@ static int __init ingenic_intc_of_init(struct device_node *node,
 	}
 
 	intc->num_chips = num_chips;
-	intc->base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
+	intc->base = of_iomap(node, 0);
+	if (!intc->base) {
+		err = -ENODEV;
+		goto out;
+	}
 
 	for (i = 0; i < num_chips; i++) {
 		/* Mask all irqs */
-- 
2.3.5

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

* [PATCH v3 18/37] MIPS: JZ4740: read intc base address from DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Read the base address of the SoC interrupt controller from the device
tree rather than relying upon the JZ4740_INTC_BASE_ADDR macro, in order
to remove the dependency on the asm/mach-jz4740/base.h header.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/irq.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index a154d9b..58fe64f 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -18,14 +18,13 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 
 #include <asm/io.h>
-
-#include <asm/mach-jz4740/base.h>
 #include <asm/mach-jz4740/irq.h>
 
 #include "irq.h"
@@ -110,7 +109,11 @@ static int __init ingenic_intc_of_init(struct device_node *node,
 	}
 
 	intc->num_chips = num_chips;
-	intc->base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
+	intc->base = of_iomap(node, 0);
+	if (!intc->base) {
+		err = -ENODEV;
+		goto out;
+	}
 
 	for (i = 0; i < num_chips; i++) {
 		/* Mask all irqs */
-- 
2.3.5

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

* [PATCH v3 19/37] MIPS: JZ4740: avoid JZ4740-specific naming
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Rename the functions including jz4740 in their names to be more generic
in preparation for supporting further SoCs, and for moving this
interrupt controller code to drivers/irqchip.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/gpio.c |  4 ++--
 arch/mips/jz4740/irq.c  | 24 ++++++++++++------------
 arch/mips/jz4740/irq.h  |  4 ++--
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c
index 00b798d..994a7df 100644
--- a/arch/mips/jz4740/gpio.c
+++ b/arch/mips/jz4740/gpio.c
@@ -442,8 +442,8 @@ static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
 	ct->chip.irq_mask = irq_gc_mask_disable_reg;
 	ct->chip.irq_unmask = jz_gpio_irq_unmask;
 	ct->chip.irq_ack = irq_gc_ack_set_bit;
-	ct->chip.irq_suspend = jz4740_irq_suspend;
-	ct->chip.irq_resume = jz4740_irq_resume;
+	ct->chip.irq_suspend = ingenic_intc_irq_suspend;
+	ct->chip.irq_resume = ingenic_intc_irq_resume;
 	ct->chip.irq_startup = jz_gpio_irq_startup;
 	ct->chip.irq_shutdown = jz_gpio_irq_shutdown;
 	ct->chip.irq_set_type = jz_gpio_irq_set_type;
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 58fe64f..65b27c8 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -43,7 +43,7 @@ struct ingenic_intc_data {
 #define JZ_REG_INTC_PENDING	0x10
 #define CHIP_SIZE		0x20
 
-static irqreturn_t jz4740_cascade(int irq, void *data)
+static irqreturn_t intc_cascade(int irq, void *data)
 {
 	struct ingenic_intc_data *intc = irq_get_handler_data(irq);
 	uint32_t irq_reg;
@@ -61,7 +61,7 @@ static irqreturn_t jz4740_cascade(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
+static void intc_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
 {
 	struct irq_chip_regs *regs = &gc->chip_types->regs;
 
@@ -69,21 +69,21 @@ static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
 	writel(~mask, gc->reg_base + regs->disable);
 }
 
-void jz4740_irq_suspend(struct irq_data *data)
+void ingenic_intc_irq_suspend(struct irq_data *data)
 {
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-	jz4740_irq_set_mask(gc, gc->wake_active);
+	intc_irq_set_mask(gc, gc->wake_active);
 }
 
-void jz4740_irq_resume(struct irq_data *data)
+void ingenic_intc_irq_resume(struct irq_data *data)
 {
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-	jz4740_irq_set_mask(gc, gc->mask_cache);
+	intc_irq_set_mask(gc, gc->mask_cache);
 }
 
-static struct irqaction jz4740_cascade_action = {
-	.handler = jz4740_cascade,
-	.name = "JZ4740 cascade interrupt",
+static struct irqaction intc_cascade_action = {
+	.handler = intc_cascade,
+	.name = "SoC intc cascade interrupt",
 };
 
 static int __init ingenic_intc_of_init(struct device_node *node,
@@ -134,8 +134,8 @@ static int __init ingenic_intc_of_init(struct device_node *node,
 		ct->chip.irq_mask = irq_gc_mask_disable_reg;
 		ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
 		ct->chip.irq_set_wake = irq_gc_set_wake;
-		ct->chip.irq_suspend = jz4740_irq_suspend;
-		ct->chip.irq_resume = jz4740_irq_resume;
+		ct->chip.irq_suspend = ingenic_intc_irq_suspend;
+		ct->chip.irq_resume = ingenic_intc_irq_resume;
 
 		irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0,
 				       IRQ_NOPROBE | IRQ_LEVEL);
@@ -150,7 +150,7 @@ static int __init ingenic_intc_of_init(struct device_node *node,
 	if (err)
 		goto out;
 
-	setup_irq(parent_irq, &jz4740_cascade_action);
+	setup_irq(parent_irq, &intc_cascade_action);
 out:
 	return err;
 }
diff --git a/arch/mips/jz4740/irq.h b/arch/mips/jz4740/irq.h
index 0f48720..601d527 100644
--- a/arch/mips/jz4740/irq.h
+++ b/arch/mips/jz4740/irq.h
@@ -17,7 +17,7 @@
 
 #include <linux/irq.h>
 
-extern void jz4740_irq_suspend(struct irq_data *data);
-extern void jz4740_irq_resume(struct irq_data *data);
+extern void ingenic_intc_irq_suspend(struct irq_data *data);
+extern void ingenic_intc_irq_resume(struct irq_data *data);
 
 #endif
-- 
2.3.5

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

* [PATCH v3 19/37] MIPS: JZ4740: avoid JZ4740-specific naming
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton

Rename the functions including jz4740 in their names to be more generic
in preparation for supporting further SoCs, and for moving this
interrupt controller code to drivers/irqchip.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/gpio.c |  4 ++--
 arch/mips/jz4740/irq.c  | 24 ++++++++++++------------
 arch/mips/jz4740/irq.h  |  4 ++--
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c
index 00b798d..994a7df 100644
--- a/arch/mips/jz4740/gpio.c
+++ b/arch/mips/jz4740/gpio.c
@@ -442,8 +442,8 @@ static void jz4740_gpio_chip_init(struct jz_gpio_chip *chip, unsigned int id)
 	ct->chip.irq_mask = irq_gc_mask_disable_reg;
 	ct->chip.irq_unmask = jz_gpio_irq_unmask;
 	ct->chip.irq_ack = irq_gc_ack_set_bit;
-	ct->chip.irq_suspend = jz4740_irq_suspend;
-	ct->chip.irq_resume = jz4740_irq_resume;
+	ct->chip.irq_suspend = ingenic_intc_irq_suspend;
+	ct->chip.irq_resume = ingenic_intc_irq_resume;
 	ct->chip.irq_startup = jz_gpio_irq_startup;
 	ct->chip.irq_shutdown = jz_gpio_irq_shutdown;
 	ct->chip.irq_set_type = jz_gpio_irq_set_type;
diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 58fe64f..65b27c8 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -43,7 +43,7 @@ struct ingenic_intc_data {
 #define JZ_REG_INTC_PENDING	0x10
 #define CHIP_SIZE		0x20
 
-static irqreturn_t jz4740_cascade(int irq, void *data)
+static irqreturn_t intc_cascade(int irq, void *data)
 {
 	struct ingenic_intc_data *intc = irq_get_handler_data(irq);
 	uint32_t irq_reg;
@@ -61,7 +61,7 @@ static irqreturn_t jz4740_cascade(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
+static void intc_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
 {
 	struct irq_chip_regs *regs = &gc->chip_types->regs;
 
@@ -69,21 +69,21 @@ static void jz4740_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
 	writel(~mask, gc->reg_base + regs->disable);
 }
 
-void jz4740_irq_suspend(struct irq_data *data)
+void ingenic_intc_irq_suspend(struct irq_data *data)
 {
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-	jz4740_irq_set_mask(gc, gc->wake_active);
+	intc_irq_set_mask(gc, gc->wake_active);
 }
 
-void jz4740_irq_resume(struct irq_data *data)
+void ingenic_intc_irq_resume(struct irq_data *data)
 {
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-	jz4740_irq_set_mask(gc, gc->mask_cache);
+	intc_irq_set_mask(gc, gc->mask_cache);
 }
 
-static struct irqaction jz4740_cascade_action = {
-	.handler = jz4740_cascade,
-	.name = "JZ4740 cascade interrupt",
+static struct irqaction intc_cascade_action = {
+	.handler = intc_cascade,
+	.name = "SoC intc cascade interrupt",
 };
 
 static int __init ingenic_intc_of_init(struct device_node *node,
@@ -134,8 +134,8 @@ static int __init ingenic_intc_of_init(struct device_node *node,
 		ct->chip.irq_mask = irq_gc_mask_disable_reg;
 		ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
 		ct->chip.irq_set_wake = irq_gc_set_wake;
-		ct->chip.irq_suspend = jz4740_irq_suspend;
-		ct->chip.irq_resume = jz4740_irq_resume;
+		ct->chip.irq_suspend = ingenic_intc_irq_suspend;
+		ct->chip.irq_resume = ingenic_intc_irq_resume;
 
 		irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0,
 				       IRQ_NOPROBE | IRQ_LEVEL);
@@ -150,7 +150,7 @@ static int __init ingenic_intc_of_init(struct device_node *node,
 	if (err)
 		goto out;
 
-	setup_irq(parent_irq, &jz4740_cascade_action);
+	setup_irq(parent_irq, &intc_cascade_action);
 out:
 	return err;
 }
diff --git a/arch/mips/jz4740/irq.h b/arch/mips/jz4740/irq.h
index 0f48720..601d527 100644
--- a/arch/mips/jz4740/irq.h
+++ b/arch/mips/jz4740/irq.h
@@ -17,7 +17,7 @@
 
 #include <linux/irq.h>
 
-extern void jz4740_irq_suspend(struct irq_data *data);
-extern void jz4740_irq_resume(struct irq_data *data);
+extern void ingenic_intc_irq_suspend(struct irq_data *data);
+extern void ingenic_intc_irq_resume(struct irq_data *data);
 
 #endif
-- 
2.3.5

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

* [PATCH v3 20/37] MIPS: JZ4740: support newer SoC interrupt controllers
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Allow the interrupt controllers of the JZ4770, JZ4775 & JZ4780 SoCs to
be probed via devicetree, supporting the 64 interrupts they provide.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - Support JZ4775, and use a more generic "2chip" probe function name
    for doing so whilst sharing code with the JZ4780.

Changes in v2:
  - None.
---
 arch/mips/jz4740/irq.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 65b27c8..5f4ec08 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -161,3 +161,12 @@ static int __init intc_1chip_of_init(struct device_node *node,
 	return ingenic_intc_of_init(node, 1);
 }
 IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init);
+
+static int __init intc_2chip_of_init(struct device_node *node,
+	struct device_node *parent)
+{
+	return ingenic_intc_of_init(node, 2);
+}
+IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init);
+IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init);
+IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init);
-- 
2.3.5

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

* [PATCH v3 20/37] MIPS: JZ4740: support newer SoC interrupt controllers
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Allow the interrupt controllers of the JZ4770, JZ4775 & JZ4780 SoCs to
be probed via devicetree, supporting the 64 interrupts they provide.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - Support JZ4775, and use a more generic "2chip" probe function name
    for doing so whilst sharing code with the JZ4780.

Changes in v2:
  - None.
---
 arch/mips/jz4740/irq.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
index 65b27c8..5f4ec08 100644
--- a/arch/mips/jz4740/irq.c
+++ b/arch/mips/jz4740/irq.c
@@ -161,3 +161,12 @@ static int __init intc_1chip_of_init(struct device_node *node,
 	return ingenic_intc_of_init(node, 1);
 }
 IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init);
+
+static int __init intc_2chip_of_init(struct device_node *node,
+	struct device_node *parent)
+{
+	return ingenic_intc_of_init(node, 2);
+}
+IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init);
+IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init);
+IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init);
-- 
2.3.5

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

* [PATCH v3 21/37] irqchip: move Ingenic SoC intc driver to drivers/irqchip
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Move the driver for Ingenic SoC interrupt controllers into
drivers/irqchip where it belongs.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/Makefile                                 | 2 +-
 arch/mips/jz4740/gpio.c                                   | 3 +--
 drivers/irqchip/Kconfig                                   | 5 +++++
 drivers/irqchip/Makefile                                  | 1 +
 arch/mips/jz4740/irq.c => drivers/irqchip/irq-ingenic.c   | 5 ++---
 arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h | 4 ++--
 6 files changed, 12 insertions(+), 8 deletions(-)
 rename arch/mips/jz4740/irq.c => drivers/irqchip/irq-ingenic.c (98%)
 rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (90%)

diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 28e5535..6cf5dd4 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y += prom.o irq.o time.o reset.o setup.o \
+obj-y += prom.o time.o reset.o setup.o \
 	gpio.o clock.o platform.o timer.o serial.o
 
 obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c
index 994a7df..54c80d4 100644
--- a/arch/mips/jz4740/gpio.c
+++ b/arch/mips/jz4740/gpio.c
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/irqchip/ingenic.h>
 #include <linux/bitops.h>
 
 #include <linux/debugfs.h>
@@ -28,8 +29,6 @@
 
 #include <asm/mach-jz4740/base.h>
 
-#include "irq.h"
-
 #define JZ4740_GPIO_BASE_A (32*0)
 #define JZ4740_GPIO_BASE_B (32*1)
 #define JZ4740_GPIO_BASE_C (32*2)
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 6de62a9..1378aca 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -158,3 +158,8 @@ config KEYSTONE_IRQ
 config MIPS_GIC
 	bool
 	select MIPS_CM
+
+config INGENIC_IRQ
+	bool
+	depends on MACH_INGENIC
+	default y
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index dda4927..982eb84 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_KEYSTONE_IRQ)		+= irq-keystone.o
 obj-$(CONFIG_MIPS_GIC)			+= irq-mips-gic.o
 obj-$(CONFIG_ARCH_MEDIATEK)		+= irq-mtk-sysirq.o
 obj-$(CONFIG_ARCH_DIGICOLOR)		+= irq-digicolor.o
+obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
diff --git a/arch/mips/jz4740/irq.c b/drivers/irqchip/irq-ingenic.c
similarity index 98%
rename from arch/mips/jz4740/irq.c
rename to drivers/irqchip/irq-ingenic.c
index 5f4ec08..1578c51 100644
--- a/arch/mips/jz4740/irq.c
+++ b/drivers/irqchip/irq-ingenic.c
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/irqchip/ingenic.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/timex.h>
@@ -27,9 +28,7 @@
 #include <asm/io.h>
 #include <asm/mach-jz4740/irq.h>
 
-#include "irq.h"
-
-#include "../../drivers/irqchip/irqchip.h"
+#include "irqchip.h"
 
 struct ingenic_intc_data {
 	void __iomem *base;
diff --git a/arch/mips/jz4740/irq.h b/include/linux/irqchip/ingenic.h
similarity index 90%
rename from arch/mips/jz4740/irq.h
rename to include/linux/irqchip/ingenic.h
index 601d527..0ee319a 100644
--- a/arch/mips/jz4740/irq.h
+++ b/include/linux/irqchip/ingenic.h
@@ -12,8 +12,8 @@
  *
  */
 
-#ifndef __MIPS_JZ4740_IRQ_H__
-#define __MIPS_JZ4740_IRQ_H__
+#ifndef __LINUX_IRQCHIP_INGENIC_H__
+#define __LINUX_IRQCHIP_INGENIC_H__
 
 #include <linux/irq.h>
 
-- 
2.3.5

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

* [PATCH v3 21/37] irqchip: move Ingenic SoC intc driver to drivers/irqchip
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

Move the driver for Ingenic SoC interrupt controllers into
drivers/irqchip where it belongs.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
---
Changes in v3:
  - New patch.
---
 arch/mips/jz4740/Makefile                                 | 2 +-
 arch/mips/jz4740/gpio.c                                   | 3 +--
 drivers/irqchip/Kconfig                                   | 5 +++++
 drivers/irqchip/Makefile                                  | 1 +
 arch/mips/jz4740/irq.c => drivers/irqchip/irq-ingenic.c   | 5 ++---
 arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h | 4 ++--
 6 files changed, 12 insertions(+), 8 deletions(-)
 rename arch/mips/jz4740/irq.c => drivers/irqchip/irq-ingenic.c (98%)
 rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (90%)

diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 28e5535..6cf5dd4 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y += prom.o irq.o time.o reset.o setup.o \
+obj-y += prom.o time.o reset.o setup.o \
 	gpio.o clock.o platform.o timer.o serial.o
 
 obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
diff --git a/arch/mips/jz4740/gpio.c b/arch/mips/jz4740/gpio.c
index 994a7df..54c80d4 100644
--- a/arch/mips/jz4740/gpio.c
+++ b/arch/mips/jz4740/gpio.c
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/irqchip/ingenic.h>
 #include <linux/bitops.h>
 
 #include <linux/debugfs.h>
@@ -28,8 +29,6 @@
 
 #include <asm/mach-jz4740/base.h>
 
-#include "irq.h"
-
 #define JZ4740_GPIO_BASE_A (32*0)
 #define JZ4740_GPIO_BASE_B (32*1)
 #define JZ4740_GPIO_BASE_C (32*2)
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 6de62a9..1378aca 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -158,3 +158,8 @@ config KEYSTONE_IRQ
 config MIPS_GIC
 	bool
 	select MIPS_CM
+
+config INGENIC_IRQ
+	bool
+	depends on MACH_INGENIC
+	default y
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index dda4927..982eb84 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_KEYSTONE_IRQ)		+= irq-keystone.o
 obj-$(CONFIG_MIPS_GIC)			+= irq-mips-gic.o
 obj-$(CONFIG_ARCH_MEDIATEK)		+= irq-mtk-sysirq.o
 obj-$(CONFIG_ARCH_DIGICOLOR)		+= irq-digicolor.o
+obj-$(CONFIG_INGENIC_IRQ)		+= irq-ingenic.o
diff --git a/arch/mips/jz4740/irq.c b/drivers/irqchip/irq-ingenic.c
similarity index 98%
rename from arch/mips/jz4740/irq.c
rename to drivers/irqchip/irq-ingenic.c
index 5f4ec08..1578c51 100644
--- a/arch/mips/jz4740/irq.c
+++ b/drivers/irqchip/irq-ingenic.c
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/irqchip/ingenic.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/timex.h>
@@ -27,9 +28,7 @@
 #include <asm/io.h>
 #include <asm/mach-jz4740/irq.h>
 
-#include "irq.h"
-
-#include "../../drivers/irqchip/irqchip.h"
+#include "irqchip.h"
 
 struct ingenic_intc_data {
 	void __iomem *base;
diff --git a/arch/mips/jz4740/irq.h b/include/linux/irqchip/ingenic.h
similarity index 90%
rename from arch/mips/jz4740/irq.h
rename to include/linux/irqchip/ingenic.h
index 601d527..0ee319a 100644
--- a/arch/mips/jz4740/irq.h
+++ b/include/linux/irqchip/ingenic.h
@@ -12,8 +12,8 @@
  *
  */
 
-#ifndef __MIPS_JZ4740_IRQ_H__
-#define __MIPS_JZ4740_IRQ_H__
+#ifndef __LINUX_IRQCHIP_INGENIC_H__
+#define __LINUX_IRQCHIP_INGENIC_H__
 
 #include <linux/irq.h>
 
-- 
2.3.5

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

* [PATCH v3 22/37] MIPS: JZ4740: call jz4740_clock_init earlier
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Call jz4740_clock_init before any uses of jz4740_clock_bdata occur. This
is in preparation for replacing uses of that struct with calls to
clk_get_rate, which will allow the clocks to be migrated towards common
clock framework & devicetree.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/clock.h | 2 ++
 arch/mips/jz4740/clock.c                  | 3 +--
 arch/mips/jz4740/time.c                   | 2 ++
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h
index 16659cd..01d8468 100644
--- a/arch/mips/include/asm/mach-jz4740/clock.h
+++ b/arch/mips/include/asm/mach-jz4740/clock.h
@@ -20,6 +20,8 @@ enum jz4740_wait_mode {
 	JZ4740_WAIT_MODE_SLEEP,
 };
 
+int jz4740_clock_init(void);
+
 void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode);
 
 void jz4740_clock_udc_enable_auto_suspend(void);
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index 1b5f554..c257073 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -889,7 +889,7 @@ void jz4740_clock_resume(void)
 		JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
 }
 
-static int jz4740_clock_init(void)
+int jz4740_clock_init(void)
 {
 	uint32_t val;
 
@@ -921,4 +921,3 @@ static int jz4740_clock_init(void)
 
 	return 0;
 }
-arch_initcall(jz4740_clock_init);
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index 72b0cecb..78ed765 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -20,6 +20,7 @@
 #include <linux/clockchips.h>
 #include <linux/sched_clock.h>
 
+#include <asm/mach-jz4740/clock.h>
 #include <asm/mach-jz4740/irq.h>
 #include <asm/mach-jz4740/timer.h>
 #include <asm/time.h>
@@ -115,6 +116,7 @@ void __init plat_time_init(void)
 	uint32_t clk_rate;
 	uint16_t ctrl;
 
+	jz4740_clock_init();
 	jz4740_timer_init();
 
 	clk_rate = jz4740_clock_bdata.ext_rate >> 4;
-- 
2.3.5

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

* [PATCH v3 22/37] MIPS: JZ4740: call jz4740_clock_init earlier
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Call jz4740_clock_init before any uses of jz4740_clock_bdata occur. This
is in preparation for replacing uses of that struct with calls to
clk_get_rate, which will allow the clocks to be migrated towards common
clock framework & devicetree.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/clock.h | 2 ++
 arch/mips/jz4740/clock.c                  | 3 +--
 arch/mips/jz4740/time.c                   | 2 ++
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h
index 16659cd..01d8468 100644
--- a/arch/mips/include/asm/mach-jz4740/clock.h
+++ b/arch/mips/include/asm/mach-jz4740/clock.h
@@ -20,6 +20,8 @@ enum jz4740_wait_mode {
 	JZ4740_WAIT_MODE_SLEEP,
 };
 
+int jz4740_clock_init(void);
+
 void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode);
 
 void jz4740_clock_udc_enable_auto_suspend(void);
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index 1b5f554..c257073 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -889,7 +889,7 @@ void jz4740_clock_resume(void)
 		JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
 }
 
-static int jz4740_clock_init(void)
+int jz4740_clock_init(void)
 {
 	uint32_t val;
 
@@ -921,4 +921,3 @@ static int jz4740_clock_init(void)
 
 	return 0;
 }
-arch_initcall(jz4740_clock_init);
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index 72b0cecb..78ed765 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -20,6 +20,7 @@
 #include <linux/clockchips.h>
 #include <linux/sched_clock.h>
 
+#include <asm/mach-jz4740/clock.h>
 #include <asm/mach-jz4740/irq.h>
 #include <asm/mach-jz4740/timer.h>
 #include <asm/time.h>
@@ -115,6 +116,7 @@ void __init plat_time_init(void)
 	uint32_t clk_rate;
 	uint16_t ctrl;
 
+	jz4740_clock_init();
 	jz4740_timer_init();
 
 	clk_rate = jz4740_clock_bdata.ext_rate >> 4;
-- 
2.3.5

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

* [PATCH v3 23/37] MIPS: JZ4740: replace use of jz4740_clock_bdata
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Replace uses of the jz4740_clock_bdata struct with calls to clk_get_rate
for the appropriate clock. This is in preparation for migrating the
clocks towards common clock framework & devicetree.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/platform.c | 11 ++++++++++-
 arch/mips/jz4740/reset.c    | 13 +++++++++++--
 arch/mips/jz4740/time.c     |  9 ++++++++-
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index 0b12f27..2a5c7c7 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
@@ -308,9 +309,17 @@ static struct platform_device jz4740_uart_device = {
 void jz4740_serial_device_register(void)
 {
 	struct plat_serial8250_port *p;
+	struct clk *ext_clk;
+	unsigned long ext_rate;
+
+	ext_clk = clk_get(NULL, "ext");
+	if (IS_ERR(ext_clk))
+		panic("unable to get ext clock");
+	ext_rate = clk_get_rate(ext_clk);
+	clk_put(ext_clk);
 
 	for (p = jz4740_uart_data; p->flags != 0; ++p)
-		p->uartclk = jz4740_clock_bdata.ext_rate;
+		p->uartclk = ext_rate;
 
 	platform_device_register(&jz4740_uart_device);
 }
diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c
index b6c6343..954e669 100644
--- a/arch/mips/jz4740/reset.c
+++ b/arch/mips/jz4740/reset.c
@@ -12,6 +12,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/pm.h>
@@ -79,12 +80,20 @@ static void jz4740_power_off(void)
 	void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38);
 	unsigned long wakeup_filter_ticks;
 	unsigned long reset_counter_ticks;
+	struct clk *rtc_clk;
+	unsigned long rtc_rate;
+
+	rtc_clk = clk_get(NULL, "rtc");
+	if (IS_ERR(rtc_clk))
+		panic("unable to get RTC clock");
+	rtc_rate = clk_get_rate(rtc_clk);
+	clk_put(rtc_clk);
 
 	/*
 	 * Set minimum wakeup pin assertion time: 100 ms.
 	 * Range is 0 to 2 sec if RTC is clocked at 32 kHz.
 	 */
-	wakeup_filter_ticks = (100 * jz4740_clock_bdata.rtc_rate) / 1000;
+	wakeup_filter_ticks = (100 * rtc_rate) / 1000;
 	if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
 		wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
 	else
@@ -96,7 +105,7 @@ static void jz4740_power_off(void)
 	 * Set reset pin low-level assertion time after wakeup: 60 ms.
 	 * Range is 0 to 125 ms if RTC is clocked at 32 kHz.
 	 */
-	reset_counter_ticks = (60 * jz4740_clock_bdata.rtc_rate) / 1000;
+	reset_counter_ticks = (60 * rtc_rate) / 1000;
 	if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK)
 		reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK;
 	else
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index 78ed765..f66f7f5 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
@@ -115,11 +116,17 @@ void __init plat_time_init(void)
 	int ret;
 	uint32_t clk_rate;
 	uint16_t ctrl;
+	struct clk *ext_clk;
 
 	jz4740_clock_init();
 	jz4740_timer_init();
 
-	clk_rate = jz4740_clock_bdata.ext_rate >> 4;
+	ext_clk = clk_get(NULL, "ext");
+	if (IS_ERR(ext_clk))
+		panic("unable to get ext clock");
+	clk_rate = clk_get_rate(ext_clk) >> 4;
+	clk_put(ext_clk);
+
 	jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ);
 
 	clockevent_set_clock(&jz4740_clockevent, clk_rate);
-- 
2.3.5

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

* [PATCH v3 23/37] MIPS: JZ4740: replace use of jz4740_clock_bdata
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Replace uses of the jz4740_clock_bdata struct with calls to clk_get_rate
for the appropriate clock. This is in preparation for migrating the
clocks towards common clock framework & devicetree.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/platform.c | 11 ++++++++++-
 arch/mips/jz4740/reset.c    | 13 +++++++++++--
 arch/mips/jz4740/time.c     |  9 ++++++++-
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index 0b12f27..2a5c7c7 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
@@ -308,9 +309,17 @@ static struct platform_device jz4740_uart_device = {
 void jz4740_serial_device_register(void)
 {
 	struct plat_serial8250_port *p;
+	struct clk *ext_clk;
+	unsigned long ext_rate;
+
+	ext_clk = clk_get(NULL, "ext");
+	if (IS_ERR(ext_clk))
+		panic("unable to get ext clock");
+	ext_rate = clk_get_rate(ext_clk);
+	clk_put(ext_clk);
 
 	for (p = jz4740_uart_data; p->flags != 0; ++p)
-		p->uartclk = jz4740_clock_bdata.ext_rate;
+		p->uartclk = ext_rate;
 
 	platform_device_register(&jz4740_uart_device);
 }
diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c
index b6c6343..954e669 100644
--- a/arch/mips/jz4740/reset.c
+++ b/arch/mips/jz4740/reset.c
@@ -12,6 +12,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/pm.h>
@@ -79,12 +80,20 @@ static void jz4740_power_off(void)
 	void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38);
 	unsigned long wakeup_filter_ticks;
 	unsigned long reset_counter_ticks;
+	struct clk *rtc_clk;
+	unsigned long rtc_rate;
+
+	rtc_clk = clk_get(NULL, "rtc");
+	if (IS_ERR(rtc_clk))
+		panic("unable to get RTC clock");
+	rtc_rate = clk_get_rate(rtc_clk);
+	clk_put(rtc_clk);
 
 	/*
 	 * Set minimum wakeup pin assertion time: 100 ms.
 	 * Range is 0 to 2 sec if RTC is clocked at 32 kHz.
 	 */
-	wakeup_filter_ticks = (100 * jz4740_clock_bdata.rtc_rate) / 1000;
+	wakeup_filter_ticks = (100 * rtc_rate) / 1000;
 	if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
 		wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
 	else
@@ -96,7 +105,7 @@ static void jz4740_power_off(void)
 	 * Set reset pin low-level assertion time after wakeup: 60 ms.
 	 * Range is 0 to 125 ms if RTC is clocked at 32 kHz.
 	 */
-	reset_counter_ticks = (60 * jz4740_clock_bdata.rtc_rate) / 1000;
+	reset_counter_ticks = (60 * rtc_rate) / 1000;
 	if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK)
 		reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK;
 	else
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index 78ed765..f66f7f5 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -13,6 +13,7 @@
  *
  */
 
+#include <linux/clk.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
@@ -115,11 +116,17 @@ void __init plat_time_init(void)
 	int ret;
 	uint32_t clk_rate;
 	uint16_t ctrl;
+	struct clk *ext_clk;
 
 	jz4740_clock_init();
 	jz4740_timer_init();
 
-	clk_rate = jz4740_clock_bdata.ext_rate >> 4;
+	ext_clk = clk_get(NULL, "ext");
+	if (IS_ERR(ext_clk))
+		panic("unable to get ext clock");
+	clk_rate = clk_get_rate(ext_clk) >> 4;
+	clk_put(ext_clk);
+
 	jz4740_jiffies_per_tick = DIV_ROUND_CLOSEST(clk_rate, HZ);
 
 	clockevent_set_clock(&jz4740_clockevent, clk_rate);
-- 
2.3.5

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

* [PATCH v3 24/37] devicetree: add Ingenic CGU binding documentation
  2015-04-21 14:46 ` Paul Burton
  (?)
@ 2015-04-21 14:46     ` Paul Burton
  -1 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips-6z/3iImG2C8G8FEW9MqTrA
  Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Document the devicetree binding for Ingenic SoC CGUs, and add headers
defining the clock specifiers for clocks provided by the JZ4740 & JZ4780
CGU blocks.

Signed-off-by: Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
Cc: Lars-Peter Clausen <lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
Cc: Mike Turquette <mturquette-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
Changes in v3:
  - Merge binding documentation for various Ingenic SoCs which differ only
    by compatible strings.

Changes in v2:
  - None.
---
 .../devicetree/bindings/clock/ingenic,cgu.txt      | 53 +++++++++++++
 include/dt-bindings/clock/jz4740-cgu.h             | 37 +++++++++
 include/dt-bindings/clock/jz4780-cgu.h             | 88 ++++++++++++++++++++++
 3 files changed, 178 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
 create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
 create mode 100644 include/dt-bindings/clock/jz4780-cgu.h

diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.txt b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
new file mode 100644
index 0000000..7421f8c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
@@ -0,0 +1,53 @@
+Ingenic SoC CGU binding
+
+The CGU in an Ingenic SoC provides all the clocks generated on-chip. It
+typically includes a variety of PLLs, multiplexers, dividers & gates in order
+to provide many different clock signals derived from only 2 external source
+clocks.
+
+Required properties:
+- compatible : Should be "ingenic,<soctype>-cgu".
+  For example "ingenic,jz4740-cgu" or "ingenic,jz4780-cgu".
+- reg : The address & length of the CGU registers.
+- clocks : List of phandle & clock specifiers for clocks external to the TCU.
+  Two such external clocks should be specified - first the external crystal
+  "ext" and second the RTC clock source "rtc".
+- clock-names : List of name strings for the external clocks.
+- #clock-cells: Should be 1.
+  Clock consumers specify this argument to identify a clock. The valid values
+  may be found in <dt-bindings/clock/<soctype>-cgu.h>.
+
+Example SoC include file:
+
+/ {
+	cgu: jz4740-cgu {
+		compatible = "ingenic,jz4740-cgu";
+		reg = <0x10000000 0x100>;
+		#clock-cells = <1>;
+	};
+
+	uart0: serial@10030000 {
+		clocks = <&cgu JZ4740_CLK_UART0>;
+	};
+};
+
+Example board file:
+
+/ {
+	ext: clock@0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <12000000>;
+	};
+
+	rtc: clock@1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	&cgu {
+		clocks = <&ext> <&rtc>;
+		clock-names: "ext", "rtc";
+	};
+};
diff --git a/include/dt-bindings/clock/jz4740-cgu.h b/include/dt-bindings/clock/jz4740-cgu.h
new file mode 100644
index 0000000..43153d3
--- /dev/null
+++ b/include/dt-bindings/clock/jz4740-cgu.h
@@ -0,0 +1,37 @@
+/*
+ * This header provides clock numbers for the ingenic,jz4740-cgu DT binding.
+ *
+ * They are roughly ordered as:
+ *   - external clocks
+ *   - PLLs
+ *   - muxes/dividers in the order they appear in the jz4740 programmers manual
+ *   - gates in order of their bit in the CLKGR* registers
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
+
+#define JZ4740_CLK_EXT		0
+#define JZ4740_CLK_RTC		1
+#define JZ4740_CLK_PLL		2
+#define JZ4740_CLK_PLL_HALF	3
+#define JZ4740_CLK_CCLK		4
+#define JZ4740_CLK_HCLK		5
+#define JZ4740_CLK_PCLK		6
+#define JZ4740_CLK_MCLK		7
+#define JZ4740_CLK_LCD		8
+#define JZ4740_CLK_LCD_PCLK	9
+#define JZ4740_CLK_I2S		10
+#define JZ4740_CLK_SPI		11
+#define JZ4740_CLK_MMC		12
+#define JZ4740_CLK_UHC		13
+#define JZ4740_CLK_UDC		14
+#define JZ4740_CLK_UART0	15
+#define JZ4740_CLK_UART1	16
+#define JZ4740_CLK_DMA		17
+#define JZ4740_CLK_IPU		18
+#define JZ4740_CLK_ADC		19
+#define JZ4740_CLK_I2C		20
+#define JZ4740_CLK_AIC		21
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ */
diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h
new file mode 100644
index 0000000..467165e
--- /dev/null
+++ b/include/dt-bindings/clock/jz4780-cgu.h
@@ -0,0 +1,88 @@
+/*
+ * This header provides clock numbers for the ingenic,jz4780-cgu DT binding.
+ *
+ * They are roughly ordered as:
+ *   - external clocks
+ *   - PLLs
+ *   - muxes/dividers in the order they appear in the jz4780 programmers manual
+ *   - gates in order of their bit in the CLKGR* registers
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+
+#define JZ4780_CLK_EXCLK	0
+#define JZ4780_CLK_RTCLK	1
+#define JZ4780_CLK_APLL		2
+#define JZ4780_CLK_MPLL		3
+#define JZ4780_CLK_EPLL		4
+#define JZ4780_CLK_VPLL		5
+#define JZ4780_CLK_OTGPHY	6
+#define JZ4780_CLK_SCLKA	7
+#define JZ4780_CLK_CPUMUX	8
+#define JZ4780_CLK_CPU		9
+#define JZ4780_CLK_L2CACHE	10
+#define JZ4780_CLK_AHB0		11
+#define JZ4780_CLK_AHB2PMUX	12
+#define JZ4780_CLK_AHB2		13
+#define JZ4780_CLK_PCLK		14
+#define JZ4780_CLK_DDR		15
+#define JZ4780_CLK_VPU		16
+#define JZ4780_CLK_I2SPLL	17
+#define JZ4780_CLK_I2S		18
+#define JZ4780_CLK_LCD0PIXCLK	19
+#define JZ4780_CLK_LCD1PIXCLK	20
+#define JZ4780_CLK_MSCMUX	21
+#define JZ4780_CLK_MSC0		22
+#define JZ4780_CLK_MSC1		23
+#define JZ4780_CLK_MSC2		24
+#define JZ4780_CLK_UHC		25
+#define JZ4780_CLK_SSIPLL	26
+#define JZ4780_CLK_SSI		27
+#define JZ4780_CLK_CIMMCLK	28
+#define JZ4780_CLK_PCMPLL	29
+#define JZ4780_CLK_PCM		30
+#define JZ4780_CLK_GPU		31
+#define JZ4780_CLK_HDMI		32
+#define JZ4780_CLK_BCH		33
+#define JZ4780_CLK_NEMC		34
+#define JZ4780_CLK_OTG0		35
+#define JZ4780_CLK_SSI0		36
+#define JZ4780_CLK_SMB0		37
+#define JZ4780_CLK_SMB1		38
+#define JZ4780_CLK_SCC		39
+#define JZ4780_CLK_AIC		40
+#define JZ4780_CLK_TSSI0	41
+#define JZ4780_CLK_OWI		42
+#define JZ4780_CLK_KBC		43
+#define JZ4780_CLK_SADC		44
+#define JZ4780_CLK_UART0	45
+#define JZ4780_CLK_UART1	46
+#define JZ4780_CLK_UART2	47
+#define JZ4780_CLK_UART3	48
+#define JZ4780_CLK_SSI1		49
+#define JZ4780_CLK_SSI2		50
+#define JZ4780_CLK_PDMA		51
+#define JZ4780_CLK_GPS		52
+#define JZ4780_CLK_MAC		53
+#define JZ4780_CLK_SMB2		54
+#define JZ4780_CLK_CIM		55
+#define JZ4780_CLK_LCD		56
+#define JZ4780_CLK_TVE		57
+#define JZ4780_CLK_IPU		58
+#define JZ4780_CLK_DDR0		59
+#define JZ4780_CLK_DDR1		60
+#define JZ4780_CLK_SMB3		61
+#define JZ4780_CLK_TSSI1	62
+#define JZ4780_CLK_COMPRESS	63
+#define JZ4780_CLK_AIC1		64
+#define JZ4780_CLK_GPVLC	65
+#define JZ4780_CLK_OTG1		66
+#define JZ4780_CLK_UART4	67
+#define JZ4780_CLK_AHBMON	68
+#define JZ4780_CLK_SMB4		69
+#define JZ4780_CLK_DES		70
+#define JZ4780_CLK_X2D		71
+#define JZ4780_CLK_CORE1	72
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */
-- 
2.3.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 24/37] devicetree: add Ingenic CGU binding documentation
@ 2015-04-21 14:46     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette, devicetree

Document the devicetree binding for Ingenic SoC CGUs, and add headers
defining the clock specifiers for clocks provided by the JZ4740 & JZ4780
CGU blocks.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - Merge binding documentation for various Ingenic SoCs which differ only
    by compatible strings.

Changes in v2:
  - None.
---
 .../devicetree/bindings/clock/ingenic,cgu.txt      | 53 +++++++++++++
 include/dt-bindings/clock/jz4740-cgu.h             | 37 +++++++++
 include/dt-bindings/clock/jz4780-cgu.h             | 88 ++++++++++++++++++++++
 3 files changed, 178 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
 create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
 create mode 100644 include/dt-bindings/clock/jz4780-cgu.h

diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.txt b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
new file mode 100644
index 0000000..7421f8c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
@@ -0,0 +1,53 @@
+Ingenic SoC CGU binding
+
+The CGU in an Ingenic SoC provides all the clocks generated on-chip. It
+typically includes a variety of PLLs, multiplexers, dividers & gates in order
+to provide many different clock signals derived from only 2 external source
+clocks.
+
+Required properties:
+- compatible : Should be "ingenic,<soctype>-cgu".
+  For example "ingenic,jz4740-cgu" or "ingenic,jz4780-cgu".
+- reg : The address & length of the CGU registers.
+- clocks : List of phandle & clock specifiers for clocks external to the TCU.
+  Two such external clocks should be specified - first the external crystal
+  "ext" and second the RTC clock source "rtc".
+- clock-names : List of name strings for the external clocks.
+- #clock-cells: Should be 1.
+  Clock consumers specify this argument to identify a clock. The valid values
+  may be found in <dt-bindings/clock/<soctype>-cgu.h>.
+
+Example SoC include file:
+
+/ {
+	cgu: jz4740-cgu {
+		compatible = "ingenic,jz4740-cgu";
+		reg = <0x10000000 0x100>;
+		#clock-cells = <1>;
+	};
+
+	uart0: serial@10030000 {
+		clocks = <&cgu JZ4740_CLK_UART0>;
+	};
+};
+
+Example board file:
+
+/ {
+	ext: clock@0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <12000000>;
+	};
+
+	rtc: clock@1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	&cgu {
+		clocks = <&ext> <&rtc>;
+		clock-names: "ext", "rtc";
+	};
+};
diff --git a/include/dt-bindings/clock/jz4740-cgu.h b/include/dt-bindings/clock/jz4740-cgu.h
new file mode 100644
index 0000000..43153d3
--- /dev/null
+++ b/include/dt-bindings/clock/jz4740-cgu.h
@@ -0,0 +1,37 @@
+/*
+ * This header provides clock numbers for the ingenic,jz4740-cgu DT binding.
+ *
+ * They are roughly ordered as:
+ *   - external clocks
+ *   - PLLs
+ *   - muxes/dividers in the order they appear in the jz4740 programmers manual
+ *   - gates in order of their bit in the CLKGR* registers
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
+
+#define JZ4740_CLK_EXT		0
+#define JZ4740_CLK_RTC		1
+#define JZ4740_CLK_PLL		2
+#define JZ4740_CLK_PLL_HALF	3
+#define JZ4740_CLK_CCLK		4
+#define JZ4740_CLK_HCLK		5
+#define JZ4740_CLK_PCLK		6
+#define JZ4740_CLK_MCLK		7
+#define JZ4740_CLK_LCD		8
+#define JZ4740_CLK_LCD_PCLK	9
+#define JZ4740_CLK_I2S		10
+#define JZ4740_CLK_SPI		11
+#define JZ4740_CLK_MMC		12
+#define JZ4740_CLK_UHC		13
+#define JZ4740_CLK_UDC		14
+#define JZ4740_CLK_UART0	15
+#define JZ4740_CLK_UART1	16
+#define JZ4740_CLK_DMA		17
+#define JZ4740_CLK_IPU		18
+#define JZ4740_CLK_ADC		19
+#define JZ4740_CLK_I2C		20
+#define JZ4740_CLK_AIC		21
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ */
diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h
new file mode 100644
index 0000000..467165e
--- /dev/null
+++ b/include/dt-bindings/clock/jz4780-cgu.h
@@ -0,0 +1,88 @@
+/*
+ * This header provides clock numbers for the ingenic,jz4780-cgu DT binding.
+ *
+ * They are roughly ordered as:
+ *   - external clocks
+ *   - PLLs
+ *   - muxes/dividers in the order they appear in the jz4780 programmers manual
+ *   - gates in order of their bit in the CLKGR* registers
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+
+#define JZ4780_CLK_EXCLK	0
+#define JZ4780_CLK_RTCLK	1
+#define JZ4780_CLK_APLL		2
+#define JZ4780_CLK_MPLL		3
+#define JZ4780_CLK_EPLL		4
+#define JZ4780_CLK_VPLL		5
+#define JZ4780_CLK_OTGPHY	6
+#define JZ4780_CLK_SCLKA	7
+#define JZ4780_CLK_CPUMUX	8
+#define JZ4780_CLK_CPU		9
+#define JZ4780_CLK_L2CACHE	10
+#define JZ4780_CLK_AHB0		11
+#define JZ4780_CLK_AHB2PMUX	12
+#define JZ4780_CLK_AHB2		13
+#define JZ4780_CLK_PCLK		14
+#define JZ4780_CLK_DDR		15
+#define JZ4780_CLK_VPU		16
+#define JZ4780_CLK_I2SPLL	17
+#define JZ4780_CLK_I2S		18
+#define JZ4780_CLK_LCD0PIXCLK	19
+#define JZ4780_CLK_LCD1PIXCLK	20
+#define JZ4780_CLK_MSCMUX	21
+#define JZ4780_CLK_MSC0		22
+#define JZ4780_CLK_MSC1		23
+#define JZ4780_CLK_MSC2		24
+#define JZ4780_CLK_UHC		25
+#define JZ4780_CLK_SSIPLL	26
+#define JZ4780_CLK_SSI		27
+#define JZ4780_CLK_CIMMCLK	28
+#define JZ4780_CLK_PCMPLL	29
+#define JZ4780_CLK_PCM		30
+#define JZ4780_CLK_GPU		31
+#define JZ4780_CLK_HDMI		32
+#define JZ4780_CLK_BCH		33
+#define JZ4780_CLK_NEMC		34
+#define JZ4780_CLK_OTG0		35
+#define JZ4780_CLK_SSI0		36
+#define JZ4780_CLK_SMB0		37
+#define JZ4780_CLK_SMB1		38
+#define JZ4780_CLK_SCC		39
+#define JZ4780_CLK_AIC		40
+#define JZ4780_CLK_TSSI0	41
+#define JZ4780_CLK_OWI		42
+#define JZ4780_CLK_KBC		43
+#define JZ4780_CLK_SADC		44
+#define JZ4780_CLK_UART0	45
+#define JZ4780_CLK_UART1	46
+#define JZ4780_CLK_UART2	47
+#define JZ4780_CLK_UART3	48
+#define JZ4780_CLK_SSI1		49
+#define JZ4780_CLK_SSI2		50
+#define JZ4780_CLK_PDMA		51
+#define JZ4780_CLK_GPS		52
+#define JZ4780_CLK_MAC		53
+#define JZ4780_CLK_SMB2		54
+#define JZ4780_CLK_CIM		55
+#define JZ4780_CLK_LCD		56
+#define JZ4780_CLK_TVE		57
+#define JZ4780_CLK_IPU		58
+#define JZ4780_CLK_DDR0		59
+#define JZ4780_CLK_DDR1		60
+#define JZ4780_CLK_SMB3		61
+#define JZ4780_CLK_TSSI1	62
+#define JZ4780_CLK_COMPRESS	63
+#define JZ4780_CLK_AIC1		64
+#define JZ4780_CLK_GPVLC	65
+#define JZ4780_CLK_OTG1		66
+#define JZ4780_CLK_UART4	67
+#define JZ4780_CLK_AHBMON	68
+#define JZ4780_CLK_SMB4		69
+#define JZ4780_CLK_DES		70
+#define JZ4780_CLK_X2D		71
+#define JZ4780_CLK_CORE1	72
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */
-- 
2.3.5

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

* [PATCH v3 24/37] devicetree: add Ingenic CGU binding documentation
@ 2015-04-21 14:46     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette, devicetree

Document the devicetree binding for Ingenic SoC CGUs, and add headers
defining the clock specifiers for clocks provided by the JZ4740 & JZ4780
CGU blocks.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - Merge binding documentation for various Ingenic SoCs which differ only
    by compatible strings.

Changes in v2:
  - None.
---
 .../devicetree/bindings/clock/ingenic,cgu.txt      | 53 +++++++++++++
 include/dt-bindings/clock/jz4740-cgu.h             | 37 +++++++++
 include/dt-bindings/clock/jz4780-cgu.h             | 88 ++++++++++++++++++++++
 3 files changed, 178 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
 create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
 create mode 100644 include/dt-bindings/clock/jz4780-cgu.h

diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.txt b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
new file mode 100644
index 0000000..7421f8c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
@@ -0,0 +1,53 @@
+Ingenic SoC CGU binding
+
+The CGU in an Ingenic SoC provides all the clocks generated on-chip. It
+typically includes a variety of PLLs, multiplexers, dividers & gates in order
+to provide many different clock signals derived from only 2 external source
+clocks.
+
+Required properties:
+- compatible : Should be "ingenic,<soctype>-cgu".
+  For example "ingenic,jz4740-cgu" or "ingenic,jz4780-cgu".
+- reg : The address & length of the CGU registers.
+- clocks : List of phandle & clock specifiers for clocks external to the TCU.
+  Two such external clocks should be specified - first the external crystal
+  "ext" and second the RTC clock source "rtc".
+- clock-names : List of name strings for the external clocks.
+- #clock-cells: Should be 1.
+  Clock consumers specify this argument to identify a clock. The valid values
+  may be found in <dt-bindings/clock/<soctype>-cgu.h>.
+
+Example SoC include file:
+
+/ {
+	cgu: jz4740-cgu {
+		compatible = "ingenic,jz4740-cgu";
+		reg = <0x10000000 0x100>;
+		#clock-cells = <1>;
+	};
+
+	uart0: serial@10030000 {
+		clocks = <&cgu JZ4740_CLK_UART0>;
+	};
+};
+
+Example board file:
+
+/ {
+	ext: clock@0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <12000000>;
+	};
+
+	rtc: clock@1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	&cgu {
+		clocks = <&ext> <&rtc>;
+		clock-names: "ext", "rtc";
+	};
+};
diff --git a/include/dt-bindings/clock/jz4740-cgu.h b/include/dt-bindings/clock/jz4740-cgu.h
new file mode 100644
index 0000000..43153d3
--- /dev/null
+++ b/include/dt-bindings/clock/jz4740-cgu.h
@@ -0,0 +1,37 @@
+/*
+ * This header provides clock numbers for the ingenic,jz4740-cgu DT binding.
+ *
+ * They are roughly ordered as:
+ *   - external clocks
+ *   - PLLs
+ *   - muxes/dividers in the order they appear in the jz4740 programmers manual
+ *   - gates in order of their bit in the CLKGR* registers
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
+
+#define JZ4740_CLK_EXT		0
+#define JZ4740_CLK_RTC		1
+#define JZ4740_CLK_PLL		2
+#define JZ4740_CLK_PLL_HALF	3
+#define JZ4740_CLK_CCLK		4
+#define JZ4740_CLK_HCLK		5
+#define JZ4740_CLK_PCLK		6
+#define JZ4740_CLK_MCLK		7
+#define JZ4740_CLK_LCD		8
+#define JZ4740_CLK_LCD_PCLK	9
+#define JZ4740_CLK_I2S		10
+#define JZ4740_CLK_SPI		11
+#define JZ4740_CLK_MMC		12
+#define JZ4740_CLK_UHC		13
+#define JZ4740_CLK_UDC		14
+#define JZ4740_CLK_UART0	15
+#define JZ4740_CLK_UART1	16
+#define JZ4740_CLK_DMA		17
+#define JZ4740_CLK_IPU		18
+#define JZ4740_CLK_ADC		19
+#define JZ4740_CLK_I2C		20
+#define JZ4740_CLK_AIC		21
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ */
diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h
new file mode 100644
index 0000000..467165e
--- /dev/null
+++ b/include/dt-bindings/clock/jz4780-cgu.h
@@ -0,0 +1,88 @@
+/*
+ * This header provides clock numbers for the ingenic,jz4780-cgu DT binding.
+ *
+ * They are roughly ordered as:
+ *   - external clocks
+ *   - PLLs
+ *   - muxes/dividers in the order they appear in the jz4780 programmers manual
+ *   - gates in order of their bit in the CLKGR* registers
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+
+#define JZ4780_CLK_EXCLK	0
+#define JZ4780_CLK_RTCLK	1
+#define JZ4780_CLK_APLL		2
+#define JZ4780_CLK_MPLL		3
+#define JZ4780_CLK_EPLL		4
+#define JZ4780_CLK_VPLL		5
+#define JZ4780_CLK_OTGPHY	6
+#define JZ4780_CLK_SCLKA	7
+#define JZ4780_CLK_CPUMUX	8
+#define JZ4780_CLK_CPU		9
+#define JZ4780_CLK_L2CACHE	10
+#define JZ4780_CLK_AHB0		11
+#define JZ4780_CLK_AHB2PMUX	12
+#define JZ4780_CLK_AHB2		13
+#define JZ4780_CLK_PCLK		14
+#define JZ4780_CLK_DDR		15
+#define JZ4780_CLK_VPU		16
+#define JZ4780_CLK_I2SPLL	17
+#define JZ4780_CLK_I2S		18
+#define JZ4780_CLK_LCD0PIXCLK	19
+#define JZ4780_CLK_LCD1PIXCLK	20
+#define JZ4780_CLK_MSCMUX	21
+#define JZ4780_CLK_MSC0		22
+#define JZ4780_CLK_MSC1		23
+#define JZ4780_CLK_MSC2		24
+#define JZ4780_CLK_UHC		25
+#define JZ4780_CLK_SSIPLL	26
+#define JZ4780_CLK_SSI		27
+#define JZ4780_CLK_CIMMCLK	28
+#define JZ4780_CLK_PCMPLL	29
+#define JZ4780_CLK_PCM		30
+#define JZ4780_CLK_GPU		31
+#define JZ4780_CLK_HDMI		32
+#define JZ4780_CLK_BCH		33
+#define JZ4780_CLK_NEMC		34
+#define JZ4780_CLK_OTG0		35
+#define JZ4780_CLK_SSI0		36
+#define JZ4780_CLK_SMB0		37
+#define JZ4780_CLK_SMB1		38
+#define JZ4780_CLK_SCC		39
+#define JZ4780_CLK_AIC		40
+#define JZ4780_CLK_TSSI0	41
+#define JZ4780_CLK_OWI		42
+#define JZ4780_CLK_KBC		43
+#define JZ4780_CLK_SADC		44
+#define JZ4780_CLK_UART0	45
+#define JZ4780_CLK_UART1	46
+#define JZ4780_CLK_UART2	47
+#define JZ4780_CLK_UART3	48
+#define JZ4780_CLK_SSI1		49
+#define JZ4780_CLK_SSI2		50
+#define JZ4780_CLK_PDMA		51
+#define JZ4780_CLK_GPS		52
+#define JZ4780_CLK_MAC		53
+#define JZ4780_CLK_SMB2		54
+#define JZ4780_CLK_CIM		55
+#define JZ4780_CLK_LCD		56
+#define JZ4780_CLK_TVE		57
+#define JZ4780_CLK_IPU		58
+#define JZ4780_CLK_DDR0		59
+#define JZ4780_CLK_DDR1		60
+#define JZ4780_CLK_SMB3		61
+#define JZ4780_CLK_TSSI1	62
+#define JZ4780_CLK_COMPRESS	63
+#define JZ4780_CLK_AIC1		64
+#define JZ4780_CLK_GPVLC	65
+#define JZ4780_CLK_OTG1		66
+#define JZ4780_CLK_UART4	67
+#define JZ4780_CLK_AHBMON	68
+#define JZ4780_CLK_SMB4		69
+#define JZ4780_CLK_DES		70
+#define JZ4780_CLK_X2D		71
+#define JZ4780_CLK_CORE1	72
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */
-- 
2.3.5

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

* [PATCH v3 25/37] clk: ingenic: add driver for Ingenic SoC CGU clocks
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

This driver supports the CGU clocks for Ingenic SoCs. It is generic
enough to be usable across at least the JZ4740 to the JZ4780, and will
be made use of on such devices in subsequent commits. This patch by
itself only adds the SoC-agnostic infrastructure that forms the bulk of
the CGU driver for the aforementioned further commits to make use of.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Co-authored-by: Paul Cercueil <paul@crapouillou.net>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - s/jz47xx/ingenic/ since Ingenic have changed their naming scheme to
    "Mxxx" for newer SoCs.

  - Allow clock gating with registers other than CLKGR* (pcercuei).

  - Fixup dividers to never exceed the requested rate (pcercuei).

  - Fixup PLL calculations to work better with more restricted
    coefficient bit widths (pcercuei).

Changes in v2:
  - Fix spinlock handling in jz47xx_clk_set_rate error path (ZubairLK).
---
 drivers/clk/Makefile         |   1 +
 drivers/clk/ingenic/Makefile |   1 +
 drivers/clk/ingenic/cgu.c    | 711 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/ingenic/cgu.h    | 223 ++++++++++++++
 4 files changed, 936 insertions(+)
 create mode 100644 drivers/clk/ingenic/Makefile
 create mode 100644 drivers/clk/ingenic/cgu.c
 create mode 100644 drivers/clk/ingenic/cgu.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25..cc77327 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
 obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
+obj-$(CONFIG_MACH_INGENIC)		+= ingenic/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
new file mode 100644
index 0000000..5ac2fd9
--- /dev/null
+++ b/drivers/clk/ingenic/Makefile
@@ -0,0 +1 @@
+obj-y				+= cgu.o
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
new file mode 100644
index 0000000..81a720e
--- /dev/null
+++ b/drivers/clk/ingenic/cgu.c
@@ -0,0 +1,713 @@
+/*
+ * Ingenic SoC CGU driver
+ *
+ * Copyright (c) 2013-2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include "cgu.h"
+
+#define MHZ (1000 * 1000)
+
+/**
+ * ingenic_cgu_gate_get - get the value of clock gate register bit
+ * @cgu: reference to the CGU whose registers should be read
+ * @idx: index of the gate bit
+ *
+ * Returns 1 if the gate bit is set, else 0. The index begins with 0 being
+ * bit 0 of CLKGR0, continuing from 32 for bit 0 of CLKGR1 etc. For example,
+ * the index of bit 9 of CLKGR1 would be (32+9) == 41.
+ *
+ * The caller must hold cgu->power_lock.
+ */
+static inline unsigned
+ingenic_cgu_gate_get(struct ingenic_cgu *cgu,
+		     const struct ingenic_cgu_gate_info *info)
+{
+	return !!(readl(cgu->base + info->reg) & BIT(info->bit));
+}
+
+/**
+ * ingenic_cgu_gate_set - set the value of clock gate register bit
+ * @cgu: reference to the CGU whose registers should be modified
+ * @idx: index of the gate bit
+ * @val: non-zero to gate a clock, otherwise zero
+ *
+ * Sets the given gate bit in order to gate or ungate a clock. See
+ * ingenic_cgu_gate_get for a description of the idx parameter.
+ *
+ * The caller must hold cgu->power_lock.
+ */
+static inline void
+ingenic_cgu_gate_set(struct ingenic_cgu *cgu,
+		     const struct ingenic_cgu_gate_info *info, bool val)
+{
+	u32 clkgr = readl(cgu->base + info->reg);
+
+	if (val)
+		clkgr |= BIT(info->bit);
+	else
+		clkgr &= ~BIT(info->bit);
+
+	writel(clkgr, cgu->base + info->reg);
+}
+
+/*
+ * PLL operations
+ */
+
+static unsigned long
+ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	const struct ingenic_cgu_pll_info *pll_info;
+	unsigned m, n, od_enc, od;
+	bool bypass, enable;
+	unsigned long flags;
+	u32 ctl;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+	BUG_ON(clk_info->type != CGU_CLK_PLL);
+	pll_info = &clk_info->pll;
+
+	spin_lock_irqsave(&cgu->pll_lock, flags);
+	ctl = readl(cgu->base + pll_info->reg);
+	spin_unlock_irqrestore(&cgu->pll_lock, flags);
+
+	m = ((ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0));
+	m += pll_info->m_offset;
+	n = ((ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0));
+	n += pll_info->n_offset;
+	od_enc = ctl >> pll_info->od_shift;
+	od_enc &= GENMASK(pll_info->od_bits - 1, 0);
+	bypass = !!(ctl & BIT(pll_info->bypass_bit));
+	enable = !!(ctl & BIT(pll_info->enable_bit));
+
+	if (bypass)
+		return parent_rate;
+
+	if (!enable)
+		return 0;
+
+	for (od = 0; od < pll_info->od_max; od++) {
+		if (pll_info->od_encoding[od] == od_enc)
+			break;
+	}
+	BUG_ON(od == pll_info->od_max);
+	od++;
+
+	return parent_rate * m / (n * od);
+}
+
+static unsigned long
+ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
+		 unsigned long rate, unsigned long parent_rate,
+		 unsigned *pm, unsigned *pn, unsigned *pod)
+{
+	unsigned m, n, od;
+
+	od = 1;
+
+	/*
+	 * The frequency after the input divider must be between 10 and 50 MHz.
+	 * The highest divider yields the best resolution.
+	 */
+	n = parent_rate / (10 * MHZ);
+	n = min_t(unsigned, n, 1 << clk_info->pll.n_bits);
+	n = max_t(unsigned, n, 1);
+
+	m = (rate / MHZ) * od * n / (parent_rate / MHZ);
+	m = min_t(unsigned, m, 1 << clk_info->pll.m_bits);
+	m = max_t(unsigned, m, 1);
+
+	if (pm)
+		*pm = m;
+	if (pn)
+		*pn = n;
+	if (pod)
+		*pod = od;
+
+	return parent_rate * m / (n * od);
+}
+
+static long
+ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
+		       unsigned long *prate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+	BUG_ON(clk_info->type != CGU_CLK_PLL);
+
+	return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
+}
+
+static int
+ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
+		     unsigned long parent_rate)
+{
+	const unsigned timeout = 100;
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	const struct ingenic_cgu_pll_info *pll_info;
+	unsigned long rate, flags;
+	unsigned m, n, od, i;
+	u32 ctl;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+	BUG_ON(clk_info->type != CGU_CLK_PLL);
+	pll_info = &clk_info->pll;
+
+	rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
+			       &m, &n, &od);
+	if (rate != req_rate)
+		pr_info("ingenic-cgu: request '%s' rate %luHz, actual %luHz\n",
+			clk_info->name, req_rate, rate);
+
+	spin_lock_irqsave(&cgu->pll_lock, flags);
+	ctl = readl(cgu->base + pll_info->reg);
+
+	ctl &= ~(GENMASK(pll_info->m_bits - 1, 0) << pll_info->m_shift);
+	ctl |= (m - pll_info->m_offset) << pll_info->m_shift;
+
+	ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift);
+	ctl |= (n - pll_info->n_offset) << pll_info->n_shift;
+
+	ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
+	ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
+
+	ctl &= ~BIT(pll_info->bypass_bit);
+	ctl |= BIT(pll_info->enable_bit);
+
+	writel(ctl, cgu->base + pll_info->reg);
+
+	/* wait for the PLL to stabilise */
+	for (i = 0; i < timeout; i++) {
+		ctl = readl(cgu->base + pll_info->reg);
+		if (ctl & BIT(pll_info->stable_bit))
+			break;
+		mdelay(1);
+	}
+
+	spin_unlock_irqrestore(&cgu->pll_lock, flags);
+
+	if (i == timeout)
+		return -EBUSY;
+
+	return 0;
+}
+
+static const struct clk_ops ingenic_pll_ops = {
+	.recalc_rate = ingenic_pll_recalc_rate,
+	.round_rate = ingenic_pll_round_rate,
+	.set_rate = ingenic_pll_set_rate,
+};
+
+/*
+ * Operations for all non-PLL clocks
+ */
+
+static u8 ingenic_clk_get_parent(struct clk_hw *hw)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	u32 reg;
+	u8 i, hw_idx, idx = 0;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_MUX) {
+		reg = readl(cgu->base + clk_info->mux.reg);
+		hw_idx = (reg >> clk_info->mux.shift) &
+			 ((1 << clk_info->mux.bits) - 1);
+
+		/*
+		 * Convert the hardware index to the parent index by skipping
+		 * over any -1's in the parents array.
+		 */
+		for (i = 0; i < hw_idx; i++) {
+			if (clk_info->parents[i] != -1)
+				idx++;
+		}
+	}
+
+	return idx;
+}
+
+static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long flags;
+	u8 curr_idx, hw_idx, num_poss;
+	u32 reg, mask;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_MUX) {
+		/*
+		 * Convert the parent index to the hardware index by adding
+		 * 1 for any -1 in the parents array preceding the given
+		 * index. That is, we want the index of idx'th entry in
+		 * clk_info->parents which does not equal -1.
+		 */
+		hw_idx = curr_idx = 0;
+		num_poss = 1 << clk_info->mux.bits;
+		for (; (hw_idx < num_poss) && (curr_idx != idx); hw_idx++) {
+			if (clk_info->parents[hw_idx] == -1)
+				continue;
+			curr_idx++;
+		}
+
+		/* idx should always be a valid parent */
+		BUG_ON(curr_idx != idx);
+
+		mask = ((1 << clk_info->mux.bits) - 1) << clk_info->mux.shift;
+
+		spin_lock_irqsave(&cgu->divmux_lock, flags);
+
+		/* write the register */
+		reg = readl(cgu->base + clk_info->mux.reg);
+		reg &= ~mask;
+		reg |= hw_idx << clk_info->mux.shift;
+		writel(reg, cgu->base + clk_info->mux.reg);
+
+		spin_unlock_irqrestore(&cgu->divmux_lock, flags);
+		return 0;
+	}
+
+	return idx ? -EINVAL : 0;
+}
+
+static unsigned long
+ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long rate = parent_rate;
+	u32 div_reg, div;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_DIV) {
+		div_reg = readl(cgu->base + clk_info->div.reg);
+		div = (div_reg >> clk_info->div.shift) &
+		      ((1 << clk_info->div.bits) - 1);
+		div += 1;
+
+		rate /= div;
+	}
+
+	return rate;
+}
+
+static unsigned
+ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info,
+		     unsigned long parent_rate, unsigned long req_rate)
+{
+	unsigned div;
+
+	/* calculate the divide */
+	div = DIV_ROUND_UP(parent_rate, req_rate);
+
+	/* and impose hardware constraints */
+	div = min_t(unsigned, div, 1 << clk_info->div.bits);
+	div = max_t(unsigned, div, 1);
+
+	return div;
+}
+
+static long
+ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
+		       unsigned long *parent_rate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	long rate = req_rate;
+	unsigned div;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_DIV) {
+		div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
+		rate = *parent_rate / div;
+	} else if (clk_info->type & CGU_CLK_FIXDIV) {
+		rate = *parent_rate / clk_info->fixdiv.div;
+	}
+
+	return rate;
+}
+
+static int
+ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
+		     unsigned long parent_rate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	const unsigned timeout = 100;
+	unsigned long rate, flags;
+	unsigned div, i;
+	u32 reg, mask;
+	int ret = 0;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_DIV) {
+		div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate);
+		rate = parent_rate / div;
+
+		if (rate != req_rate)
+			return -EINVAL;
+
+		spin_lock_irqsave(&cgu->divmux_lock, flags);
+		reg = readl(cgu->base + clk_info->div.reg);
+
+		/* update the divide */
+		mask = (1 << clk_info->div.bits) - 1;
+		reg &= ~(mask << clk_info->div.shift);
+		reg |= (div - 1) << clk_info->div.shift;
+
+		/* clear the stop bit */
+		if (clk_info->div.stop_bit != -1)
+			reg &= ~(1 << clk_info->div.stop_bit);
+
+		/* set the change enable bit */
+		if (clk_info->div.ce_bit != -1)
+			reg |= 1 << clk_info->div.ce_bit;
+
+		/* update the hardware */
+		writel(reg, cgu->base + clk_info->div.reg);
+
+		/* wait for the change to take effect */
+		if (clk_info->div.busy_bit != -1) {
+			for (i = 0; i < timeout; i++) {
+				reg = readl(cgu->base + clk_info->div.reg);
+				if (!(reg & (1 << clk_info->div.busy_bit)))
+					break;
+				mdelay(1);
+			}
+			if (i == timeout)
+				ret = -EBUSY;
+		}
+
+		spin_unlock_irqrestore(&cgu->divmux_lock, flags);
+		return ret;
+	}
+
+	return -EINVAL;
+}
+
+static int ingenic_clk_enable(struct clk_hw *hw)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long flags;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_GATE) {
+		/* ungate the clock */
+		spin_lock_irqsave(&cgu->power_lock, flags);
+		ingenic_cgu_gate_set(cgu, &clk_info->gate, false);
+		spin_unlock_irqrestore(&cgu->power_lock, flags);
+	}
+
+	return 0;
+}
+
+static void ingenic_clk_disable(struct clk_hw *hw)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long flags;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_GATE) {
+		/* gate the clock */
+		spin_lock_irqsave(&cgu->power_lock, flags);
+		ingenic_cgu_gate_set(cgu, &clk_info->gate, true);
+		spin_unlock_irqrestore(&cgu->power_lock, flags);
+	}
+}
+
+static int ingenic_clk_is_enabled(struct clk_hw *hw)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long flags;
+	int enabled = 1;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_GATE) {
+		spin_lock_irqsave(&cgu->power_lock, flags);
+		enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
+		spin_unlock_irqrestore(&cgu->power_lock, flags);
+	}
+
+	return enabled;
+}
+
+static const struct clk_ops ingenic_clk_ops = {
+	.get_parent = ingenic_clk_get_parent,
+	.set_parent = ingenic_clk_set_parent,
+
+	.recalc_rate = ingenic_clk_recalc_rate,
+	.round_rate = ingenic_clk_round_rate,
+	.set_rate = ingenic_clk_set_rate,
+
+	.enable = ingenic_clk_enable,
+	.disable = ingenic_clk_disable,
+	.is_enabled = ingenic_clk_is_enabled,
+};
+
+/*
+ * Setup functions.
+ */
+
+static int register_clock(struct ingenic_cgu *cgu, unsigned idx)
+{
+	const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx];
+	struct clk_init_data clk_init;
+	struct ingenic_clk *ingenic_clk = NULL;
+	struct clk *clk, *parent;
+	const char *parent_names[4];
+	unsigned caps, i, num_possible;
+	int err = -EINVAL;
+
+	BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names));
+
+	if (clk_info->type == CGU_CLK_EXT) {
+		clk = of_clk_get_by_name(cgu->np, clk_info->name);
+		if (IS_ERR(clk)) {
+			pr_err("%s: no external clock '%s' provided\n",
+			       __func__, clk_info->name);
+			err = -ENODEV;
+			goto out;
+		}
+		err = clk_register_clkdev(clk, clk_info->name, NULL);
+		if (err) {
+			clk_put(clk);
+			goto out;
+		}
+		cgu->clocks.clks[idx] = clk;
+		return 0;
+	}
+
+	if (!clk_info->type) {
+		pr_err("%s: no clock type specified for '%s'\n", __func__,
+		       clk_info->name);
+		goto out;
+	}
+
+	ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL);
+	if (!ingenic_clk) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	ingenic_clk->hw.init = &clk_init;
+	ingenic_clk->cgu = cgu;
+	ingenic_clk->idx = idx;
+
+	clk_init.name = clk_info->name;
+	clk_init.flags = 0;
+	clk_init.parent_names = parent_names;
+
+	caps = clk_info->type;
+
+	if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
+		clk_init.num_parents = 0;
+
+		if (caps & CGU_CLK_MUX)
+			num_possible = 1 << clk_info->mux.bits;
+		else
+			num_possible = ARRAY_SIZE(clk_info->parents);
+
+		for (i = 0; i < num_possible; i++) {
+			if (clk_info->parents[i] == -1)
+				continue;
+
+			parent = cgu->clocks.clks[clk_info->parents[i]];
+			parent_names[clk_init.num_parents] =
+				__clk_get_name(parent);
+			clk_init.num_parents++;
+		}
+
+		BUG_ON(!clk_init.num_parents);
+		BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names));
+	} else {
+		BUG_ON(clk_info->parents[0] == -1);
+		clk_init.num_parents = 1;
+		parent = cgu->clocks.clks[clk_info->parents[0]];
+		parent_names[0] = __clk_get_name(parent);
+	}
+
+	if (caps & CGU_CLK_CUSTOM) {
+		clk_init.ops = clk_info->custom.clk_ops;
+
+		caps &= ~CGU_CLK_CUSTOM;
+
+		if (caps) {
+			pr_err("%s: custom clock may not be combined with type 0x%x\n",
+			       __func__, caps);
+			goto out;
+		}
+	} else if (caps & CGU_CLK_PLL) {
+		clk_init.ops = &ingenic_pll_ops;
+
+		caps &= ~CGU_CLK_PLL;
+
+		if (caps) {
+			pr_err("%s: PLL may not be combined with type 0x%x\n",
+			       __func__, caps);
+			goto out;
+		}
+	} else {
+		clk_init.ops = &ingenic_clk_ops;
+	}
+
+	/* nothing to do for gates or fixed dividers */
+	caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV);
+
+	if (caps & CGU_CLK_MUX) {
+		if (!(caps & CGU_CLK_MUX_GLITCHFREE))
+			clk_init.flags |= CLK_SET_PARENT_GATE;
+
+		caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE);
+	}
+
+	if (caps & CGU_CLK_DIV) {
+		caps &= ~CGU_CLK_DIV;
+	} else {
+		/* pass rate changes to the parent clock */
+		clk_init.flags |= CLK_SET_RATE_PARENT;
+	}
+
+	if (caps) {
+		pr_err("%s: unknown clock type 0x%x\n", __func__, caps);
+		goto out;
+	}
+
+	clk = clk_register(NULL, &ingenic_clk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register clock '%s'\n", __func__,
+		       clk_info->name);
+		err = PTR_ERR(clk);
+		goto out;
+	}
+
+	err = clk_register_clkdev(clk, clk_info->name, NULL);
+	if (err)
+		goto out;
+
+	cgu->clocks.clks[idx] = clk;
+out:
+	if (err)
+		kfree(ingenic_clk);
+	return err;
+}
+
+struct ingenic_cgu *
+ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
+		unsigned num_clocks, struct device_node *np)
+{
+	struct ingenic_cgu *cgu;
+
+	cgu = kzalloc(sizeof(*cgu), GFP_KERNEL);
+	if (!cgu)
+		goto err_out;
+
+	cgu->base = of_iomap(np, 0);
+	if (!cgu->base) {
+		pr_err("%s: failed to map CGU registers\n", __func__);
+		goto err_out_free;
+	}
+
+	cgu->np = np;
+	cgu->clock_info = clock_info;
+	cgu->clocks.clk_num = num_clocks;
+
+	spin_lock_init(&cgu->divmux_lock);
+	spin_lock_init(&cgu->power_lock);
+	spin_lock_init(&cgu->pll_lock);
+
+	return cgu;
+
+err_out_free:
+	kfree(cgu);
+err_out:
+	return NULL;
+}
+
+int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu)
+{
+	unsigned i;
+	int err;
+
+	cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *),
+				   GFP_KERNEL);
+	if (!cgu->clocks.clks) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	for (i = 0; i < cgu->clocks.clk_num; i++) {
+		err = register_clock(cgu, i);
+		if (err)
+			goto err_out_unregister;
+	}
+
+	err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get,
+				  &cgu->clocks);
+	if (err)
+		goto err_out_unregister;
+
+	return 0;
+
+err_out_unregister:
+	if (cgu) {
+		for (i = 0; i < cgu->clocks.clk_num; i++) {
+			if (!cgu->clocks.clks[i])
+				continue;
+			if (cgu->clock_info[i].type & CGU_CLK_EXT)
+				clk_put(cgu->clocks.clks[i]);
+			else
+				clk_unregister(cgu->clocks.clks[i]);
+		}
+		kfree(cgu->clocks.clks);
+	}
+err_out:
+	return err;
+}
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
new file mode 100644
index 0000000..47e0552
--- /dev/null
+++ b/drivers/clk/ingenic/cgu.h
@@ -0,0 +1,223 @@
+/*
+ * Ingenic SoC CGU driver
+ *
+ * Copyright (c) 2013-2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRIVERS_CLK_INGENIC_CGU_H__
+#define __DRIVERS_CLK_INGENIC_CGU_H__
+
+#include <linux/of.h>
+#include <linux/spinlock.h>
+
+/**
+ * struct ingenic_cgu_pll_info - information about a PLL
+ * @reg: the offset of the PLL's control register within the CGU
+ * @m_shift: the number of bits to shift the multiplier value by (ie. the
+ *           index of the lowest bit of the multiplier value in the PLL's
+ *           control register)
+ * @m_bits: the size of the multiplier field in bits
+ * @m_offset: the multiplier value which encodes to 0 in the PLL's control
+ *            register
+ * @n_shift: the number of bits to shift the divider value by (ie. the
+ *           index of the lowest bit of the divider value in the PLL's
+ *           control register)
+ * @n_bits: the size of the divider field in bits
+ * @n_offset: the divider value which encodes to 0 in the PLL's control
+ *            register
+ * @od_shift: the number of bits to shift the post-VCO divider value by (ie.
+ *            the index of the lowest bit of the post-VCO divider value in
+ *            the PLL's control register)
+ * @od_bits: the size of the post-VCO divider field in bits
+ * @od_max: the maximum post-VCO divider value
+ * @od_encoding: a pointer to an array mapping post-VCO divider values to
+ *               their encoded values in the PLL control register, or -1 for
+ *               unsupported values
+ * @bypass_bit: the index of the bypass bit in the PLL control register
+ * @enable_bit: the index of the enable bit in the PLL control register
+ * @stable_bit: the index of the stable bit in the PLL control register
+ */
+struct ingenic_cgu_pll_info {
+	unsigned reg;
+	unsigned m_shift, m_bits, m_offset;
+	unsigned n_shift, n_bits, n_offset;
+	unsigned od_shift, od_bits, od_max;
+	const s8 *od_encoding;
+	unsigned bypass_bit;
+	unsigned enable_bit;
+	unsigned stable_bit;
+};
+
+/**
+ * struct ingenic_cgu_mux_info - information about a clock mux
+ * @reg: offset of the mux control register within the CGU
+ * @shift: number of bits to shift the mux value by (ie. the index of
+ *         the lowest bit of the mux value within its control register)
+ * @bits: the size of the mux value in bits
+ */
+struct ingenic_cgu_mux_info {
+	unsigned reg;
+	unsigned shift:5;
+	unsigned bits:5;
+};
+
+/**
+ * struct ingenic_cgu_div_info - information about a divider
+ * @reg: offset of the divider control register within the CGU
+ * @shift: number of bits to shift the divide value by (ie. the index of
+ *         the lowest bit of the divide value within its control register)
+ * @bits: the size of the divide value in bits
+ * @ce_bit: the index of the change enable bit within reg, or -1 is there
+ *          isn't one
+ * @busy_bit: the index of the busy bit within reg, or -1 is there isn't one
+ * @stop_bit: the index of the stop bit within reg, or -1 is there isn't one
+ */
+struct ingenic_cgu_div_info {
+	unsigned reg;
+	unsigned shift:5;
+	unsigned bits:5;
+	int ce_bit:6;
+	int busy_bit:6;
+	int stop_bit:6;
+};
+
+/**
+ * struct ingenic_cgu_fixdiv_info - information about a fixed divider
+ * @div: the divider applied to the parent clock
+ */
+struct ingenic_cgu_fixdiv_info {
+	unsigned div;
+};
+
+/**
+ * struct ingenic_cgu_gate_info - information about a clock gate
+ * @reg: offset of the gate control register within the CGU
+ * @bit: offset of the bit in the register that controls the gate
+ */
+struct ingenic_cgu_gate_info {
+	unsigned reg;
+	unsigned bit:5;
+};
+
+/**
+ * struct ingenic_cgu_custom_info - information about a custom (SoC) clock
+ */
+struct ingenic_cgu_custom_info {
+	struct clk_ops *clk_ops;
+};
+
+/**
+ * struct ingenic_cgu_clk_info - information about a clock
+ * @name: name of the clock
+ * @type: a bitmask formed from CGU_CLK_* values
+ * @parents: an array of the indices of potential parents of this clock
+ *           within the clock_info array of the CGU, or -1 in entries
+ *           which correspond to no valid parent
+ * @pll: information valid if type includes CGU_CLK_PLL
+ * @gate: information valid if type includes CGU_CLK_GATE
+ * @mux: information valid if type includes CGU_CLK_MUX
+ * @div: information valid if type includes CGU_CLK_DIV
+ */
+struct ingenic_cgu_clk_info {
+	const char *name;
+
+	enum {
+		CGU_CLK_NONE		= 0,
+		CGU_CLK_EXT		= (1 << 0),
+		CGU_CLK_PLL		= (1 << 1),
+		CGU_CLK_GATE		= (1 << 2),
+		CGU_CLK_MUX		= (1 << 3),
+		CGU_CLK_MUX_GLITCHFREE	= (1 << 4),
+		CGU_CLK_DIV		= (1 << 5),
+		CGU_CLK_FIXDIV		= (1 << 6),
+		CGU_CLK_CUSTOM		= (1 << 7),
+	} type;
+
+	int parents[4];
+
+	union {
+		struct ingenic_cgu_pll_info pll;
+
+		struct {
+			struct ingenic_cgu_gate_info gate;
+			struct ingenic_cgu_mux_info mux;
+			struct ingenic_cgu_div_info div;
+			struct ingenic_cgu_fixdiv_info fixdiv;
+		};
+
+		struct ingenic_cgu_custom_info custom;
+	};
+};
+
+/**
+ * struct ingenic_cgu - data about the CGU
+ * @np: the device tree node that caused the CGU to be probed
+ * @base: the ioremap'ed base address of the CGU registers
+ * @clock_info: an array containing information about implemented clocks
+ * @clocks: used to provide clocks to DT, allows lookup of struct clk*
+ * @gate_lock: lock to be held whilst (un)gating a clock
+ * @divmux_lock: lock to be held whilst re-muxing of rate-changing a clock
+ */
+struct ingenic_cgu {
+	struct device_node *np;
+	void __iomem *base;
+
+	const struct ingenic_cgu_clk_info *clock_info;
+	struct clk_onecell_data clocks;
+
+	spinlock_t divmux_lock;		/* must be held when changing a divide
+					   or re-muxing a clock */
+	spinlock_t power_lock;		/* must be held when changing a power
+					   manager register */
+	spinlock_t pll_lock;		/* must be held when changing a PLL
+					   control register */
+};
+
+/**
+ * struct ingenic_clk - private data for a clock
+ * @hw: see Documentation/clk.txt
+ * @cgu: a pointer to the CGU data
+ * @idx: the index of this clock in cgu->clock_info
+ */
+struct ingenic_clk {
+	struct clk_hw hw;
+	struct ingenic_cgu *cgu;
+	unsigned idx;
+};
+
+#define to_ingenic_clk(_hw) container_of(_hw, struct ingenic_clk, hw)
+
+/**
+ * ingenic_cgu_new - create a new CGU instance
+ * @clock_info: an array of clock information structures describing the clocks
+ *              which are implemented by the CGU
+ * @num_clocks: the number of entries in clock_info
+ * @np: the device tree node which causes this CGU to be probed
+ *
+ * Returns an opaque pointer to the CGU instance if initialisation & clock
+ * registration is successful, otherwise NULL.
+ */
+struct ingenic_cgu *
+ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
+		unsigned num_clocks, struct device_node *np);
+
+/**
+ * ingenic_cgu_register_clocks - Registers the clocks
+ * @cgu: pointer to cgu data
+ *
+ * Returns 1 on success and -EINVAL if unsuccesful.
+ */
+int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu);
+
+#endif /* __DRIVERS_CLK_INGENIC_CGU_H__ */
-- 
2.3.5

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

* [PATCH v3 25/37] clk: ingenic: add driver for Ingenic SoC CGU clocks
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

This driver supports the CGU clocks for Ingenic SoCs. It is generic
enough to be usable across at least the JZ4740 to the JZ4780, and will
be made use of on such devices in subsequent commits. This patch by
itself only adds the SoC-agnostic infrastructure that forms the bulk of
the CGU driver for the aforementioned further commits to make use of.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Co-authored-by: Paul Cercueil <paul@crapouillou.net>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - s/jz47xx/ingenic/ since Ingenic have changed their naming scheme to
    "Mxxx" for newer SoCs.

  - Allow clock gating with registers other than CLKGR* (pcercuei).

  - Fixup dividers to never exceed the requested rate (pcercuei).

  - Fixup PLL calculations to work better with more restricted
    coefficient bit widths (pcercuei).

Changes in v2:
  - Fix spinlock handling in jz47xx_clk_set_rate error path (ZubairLK).
---
 drivers/clk/Makefile         |   1 +
 drivers/clk/ingenic/Makefile |   1 +
 drivers/clk/ingenic/cgu.c    | 711 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/ingenic/cgu.h    | 223 ++++++++++++++
 4 files changed, 936 insertions(+)
 create mode 100644 drivers/clk/ingenic/Makefile
 create mode 100644 drivers/clk/ingenic/cgu.c
 create mode 100644 drivers/clk/ingenic/cgu.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25..cc77327 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
 obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
+obj-$(CONFIG_MACH_INGENIC)		+= ingenic/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
new file mode 100644
index 0000000..5ac2fd9
--- /dev/null
+++ b/drivers/clk/ingenic/Makefile
@@ -0,0 +1 @@
+obj-y				+= cgu.o
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
new file mode 100644
index 0000000..81a720e
--- /dev/null
+++ b/drivers/clk/ingenic/cgu.c
@@ -0,0 +1,713 @@
+/*
+ * Ingenic SoC CGU driver
+ *
+ * Copyright (c) 2013-2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include "cgu.h"
+
+#define MHZ (1000 * 1000)
+
+/**
+ * ingenic_cgu_gate_get - get the value of clock gate register bit
+ * @cgu: reference to the CGU whose registers should be read
+ * @idx: index of the gate bit
+ *
+ * Returns 1 if the gate bit is set, else 0. The index begins with 0 being
+ * bit 0 of CLKGR0, continuing from 32 for bit 0 of CLKGR1 etc. For example,
+ * the index of bit 9 of CLKGR1 would be (32+9) == 41.
+ *
+ * The caller must hold cgu->power_lock.
+ */
+static inline unsigned
+ingenic_cgu_gate_get(struct ingenic_cgu *cgu,
+		     const struct ingenic_cgu_gate_info *info)
+{
+	return !!(readl(cgu->base + info->reg) & BIT(info->bit));
+}
+
+/**
+ * ingenic_cgu_gate_set - set the value of clock gate register bit
+ * @cgu: reference to the CGU whose registers should be modified
+ * @idx: index of the gate bit
+ * @val: non-zero to gate a clock, otherwise zero
+ *
+ * Sets the given gate bit in order to gate or ungate a clock. See
+ * ingenic_cgu_gate_get for a description of the idx parameter.
+ *
+ * The caller must hold cgu->power_lock.
+ */
+static inline void
+ingenic_cgu_gate_set(struct ingenic_cgu *cgu,
+		     const struct ingenic_cgu_gate_info *info, bool val)
+{
+	u32 clkgr = readl(cgu->base + info->reg);
+
+	if (val)
+		clkgr |= BIT(info->bit);
+	else
+		clkgr &= ~BIT(info->bit);
+
+	writel(clkgr, cgu->base + info->reg);
+}
+
+/*
+ * PLL operations
+ */
+
+static unsigned long
+ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	const struct ingenic_cgu_pll_info *pll_info;
+	unsigned m, n, od_enc, od;
+	bool bypass, enable;
+	unsigned long flags;
+	u32 ctl;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+	BUG_ON(clk_info->type != CGU_CLK_PLL);
+	pll_info = &clk_info->pll;
+
+	spin_lock_irqsave(&cgu->pll_lock, flags);
+	ctl = readl(cgu->base + pll_info->reg);
+	spin_unlock_irqrestore(&cgu->pll_lock, flags);
+
+	m = ((ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0));
+	m += pll_info->m_offset;
+	n = ((ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0));
+	n += pll_info->n_offset;
+	od_enc = ctl >> pll_info->od_shift;
+	od_enc &= GENMASK(pll_info->od_bits - 1, 0);
+	bypass = !!(ctl & BIT(pll_info->bypass_bit));
+	enable = !!(ctl & BIT(pll_info->enable_bit));
+
+	if (bypass)
+		return parent_rate;
+
+	if (!enable)
+		return 0;
+
+	for (od = 0; od < pll_info->od_max; od++) {
+		if (pll_info->od_encoding[od] == od_enc)
+			break;
+	}
+	BUG_ON(od == pll_info->od_max);
+	od++;
+
+	return parent_rate * m / (n * od);
+}
+
+static unsigned long
+ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
+		 unsigned long rate, unsigned long parent_rate,
+		 unsigned *pm, unsigned *pn, unsigned *pod)
+{
+	unsigned m, n, od;
+
+	od = 1;
+
+	/*
+	 * The frequency after the input divider must be between 10 and 50 MHz.
+	 * The highest divider yields the best resolution.
+	 */
+	n = parent_rate / (10 * MHZ);
+	n = min_t(unsigned, n, 1 << clk_info->pll.n_bits);
+	n = max_t(unsigned, n, 1);
+
+	m = (rate / MHZ) * od * n / (parent_rate / MHZ);
+	m = min_t(unsigned, m, 1 << clk_info->pll.m_bits);
+	m = max_t(unsigned, m, 1);
+
+	if (pm)
+		*pm = m;
+	if (pn)
+		*pn = n;
+	if (pod)
+		*pod = od;
+
+	return parent_rate * m / (n * od);
+}
+
+static long
+ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
+		       unsigned long *prate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+	BUG_ON(clk_info->type != CGU_CLK_PLL);
+
+	return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
+}
+
+static int
+ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
+		     unsigned long parent_rate)
+{
+	const unsigned timeout = 100;
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	const struct ingenic_cgu_pll_info *pll_info;
+	unsigned long rate, flags;
+	unsigned m, n, od, i;
+	u32 ctl;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+	BUG_ON(clk_info->type != CGU_CLK_PLL);
+	pll_info = &clk_info->pll;
+
+	rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
+			       &m, &n, &od);
+	if (rate != req_rate)
+		pr_info("ingenic-cgu: request '%s' rate %luHz, actual %luHz\n",
+			clk_info->name, req_rate, rate);
+
+	spin_lock_irqsave(&cgu->pll_lock, flags);
+	ctl = readl(cgu->base + pll_info->reg);
+
+	ctl &= ~(GENMASK(pll_info->m_bits - 1, 0) << pll_info->m_shift);
+	ctl |= (m - pll_info->m_offset) << pll_info->m_shift;
+
+	ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift);
+	ctl |= (n - pll_info->n_offset) << pll_info->n_shift;
+
+	ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
+	ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
+
+	ctl &= ~BIT(pll_info->bypass_bit);
+	ctl |= BIT(pll_info->enable_bit);
+
+	writel(ctl, cgu->base + pll_info->reg);
+
+	/* wait for the PLL to stabilise */
+	for (i = 0; i < timeout; i++) {
+		ctl = readl(cgu->base + pll_info->reg);
+		if (ctl & BIT(pll_info->stable_bit))
+			break;
+		mdelay(1);
+	}
+
+	spin_unlock_irqrestore(&cgu->pll_lock, flags);
+
+	if (i == timeout)
+		return -EBUSY;
+
+	return 0;
+}
+
+static const struct clk_ops ingenic_pll_ops = {
+	.recalc_rate = ingenic_pll_recalc_rate,
+	.round_rate = ingenic_pll_round_rate,
+	.set_rate = ingenic_pll_set_rate,
+};
+
+/*
+ * Operations for all non-PLL clocks
+ */
+
+static u8 ingenic_clk_get_parent(struct clk_hw *hw)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	u32 reg;
+	u8 i, hw_idx, idx = 0;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_MUX) {
+		reg = readl(cgu->base + clk_info->mux.reg);
+		hw_idx = (reg >> clk_info->mux.shift) &
+			 ((1 << clk_info->mux.bits) - 1);
+
+		/*
+		 * Convert the hardware index to the parent index by skipping
+		 * over any -1's in the parents array.
+		 */
+		for (i = 0; i < hw_idx; i++) {
+			if (clk_info->parents[i] != -1)
+				idx++;
+		}
+	}
+
+	return idx;
+}
+
+static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long flags;
+	u8 curr_idx, hw_idx, num_poss;
+	u32 reg, mask;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_MUX) {
+		/*
+		 * Convert the parent index to the hardware index by adding
+		 * 1 for any -1 in the parents array preceding the given
+		 * index. That is, we want the index of idx'th entry in
+		 * clk_info->parents which does not equal -1.
+		 */
+		hw_idx = curr_idx = 0;
+		num_poss = 1 << clk_info->mux.bits;
+		for (; (hw_idx < num_poss) && (curr_idx != idx); hw_idx++) {
+			if (clk_info->parents[hw_idx] == -1)
+				continue;
+			curr_idx++;
+		}
+
+		/* idx should always be a valid parent */
+		BUG_ON(curr_idx != idx);
+
+		mask = ((1 << clk_info->mux.bits) - 1) << clk_info->mux.shift;
+
+		spin_lock_irqsave(&cgu->divmux_lock, flags);
+
+		/* write the register */
+		reg = readl(cgu->base + clk_info->mux.reg);
+		reg &= ~mask;
+		reg |= hw_idx << clk_info->mux.shift;
+		writel(reg, cgu->base + clk_info->mux.reg);
+
+		spin_unlock_irqrestore(&cgu->divmux_lock, flags);
+		return 0;
+	}
+
+	return idx ? -EINVAL : 0;
+}
+
+static unsigned long
+ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long rate = parent_rate;
+	u32 div_reg, div;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_DIV) {
+		div_reg = readl(cgu->base + clk_info->div.reg);
+		div = (div_reg >> clk_info->div.shift) &
+		      ((1 << clk_info->div.bits) - 1);
+		div += 1;
+
+		rate /= div;
+	}
+
+	return rate;
+}
+
+static unsigned
+ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info,
+		     unsigned long parent_rate, unsigned long req_rate)
+{
+	unsigned div;
+
+	/* calculate the divide */
+	div = DIV_ROUND_UP(parent_rate, req_rate);
+
+	/* and impose hardware constraints */
+	div = min_t(unsigned, div, 1 << clk_info->div.bits);
+	div = max_t(unsigned, div, 1);
+
+	return div;
+}
+
+static long
+ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
+		       unsigned long *parent_rate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	long rate = req_rate;
+	unsigned div;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_DIV) {
+		div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
+		rate = *parent_rate / div;
+	} else if (clk_info->type & CGU_CLK_FIXDIV) {
+		rate = *parent_rate / clk_info->fixdiv.div;
+	}
+
+	return rate;
+}
+
+static int
+ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
+		     unsigned long parent_rate)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	const unsigned timeout = 100;
+	unsigned long rate, flags;
+	unsigned div, i;
+	u32 reg, mask;
+	int ret = 0;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_DIV) {
+		div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate);
+		rate = parent_rate / div;
+
+		if (rate != req_rate)
+			return -EINVAL;
+
+		spin_lock_irqsave(&cgu->divmux_lock, flags);
+		reg = readl(cgu->base + clk_info->div.reg);
+
+		/* update the divide */
+		mask = (1 << clk_info->div.bits) - 1;
+		reg &= ~(mask << clk_info->div.shift);
+		reg |= (div - 1) << clk_info->div.shift;
+
+		/* clear the stop bit */
+		if (clk_info->div.stop_bit != -1)
+			reg &= ~(1 << clk_info->div.stop_bit);
+
+		/* set the change enable bit */
+		if (clk_info->div.ce_bit != -1)
+			reg |= 1 << clk_info->div.ce_bit;
+
+		/* update the hardware */
+		writel(reg, cgu->base + clk_info->div.reg);
+
+		/* wait for the change to take effect */
+		if (clk_info->div.busy_bit != -1) {
+			for (i = 0; i < timeout; i++) {
+				reg = readl(cgu->base + clk_info->div.reg);
+				if (!(reg & (1 << clk_info->div.busy_bit)))
+					break;
+				mdelay(1);
+			}
+			if (i == timeout)
+				ret = -EBUSY;
+		}
+
+		spin_unlock_irqrestore(&cgu->divmux_lock, flags);
+		return ret;
+	}
+
+	return -EINVAL;
+}
+
+static int ingenic_clk_enable(struct clk_hw *hw)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long flags;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_GATE) {
+		/* ungate the clock */
+		spin_lock_irqsave(&cgu->power_lock, flags);
+		ingenic_cgu_gate_set(cgu, &clk_info->gate, false);
+		spin_unlock_irqrestore(&cgu->power_lock, flags);
+	}
+
+	return 0;
+}
+
+static void ingenic_clk_disable(struct clk_hw *hw)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long flags;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_GATE) {
+		/* gate the clock */
+		spin_lock_irqsave(&cgu->power_lock, flags);
+		ingenic_cgu_gate_set(cgu, &clk_info->gate, true);
+		spin_unlock_irqrestore(&cgu->power_lock, flags);
+	}
+}
+
+static int ingenic_clk_is_enabled(struct clk_hw *hw)
+{
+	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
+	struct ingenic_cgu *cgu = ingenic_clk->cgu;
+	const struct ingenic_cgu_clk_info *clk_info;
+	unsigned long flags;
+	int enabled = 1;
+
+	clk_info = &cgu->clock_info[ingenic_clk->idx];
+
+	if (clk_info->type & CGU_CLK_GATE) {
+		spin_lock_irqsave(&cgu->power_lock, flags);
+		enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
+		spin_unlock_irqrestore(&cgu->power_lock, flags);
+	}
+
+	return enabled;
+}
+
+static const struct clk_ops ingenic_clk_ops = {
+	.get_parent = ingenic_clk_get_parent,
+	.set_parent = ingenic_clk_set_parent,
+
+	.recalc_rate = ingenic_clk_recalc_rate,
+	.round_rate = ingenic_clk_round_rate,
+	.set_rate = ingenic_clk_set_rate,
+
+	.enable = ingenic_clk_enable,
+	.disable = ingenic_clk_disable,
+	.is_enabled = ingenic_clk_is_enabled,
+};
+
+/*
+ * Setup functions.
+ */
+
+static int register_clock(struct ingenic_cgu *cgu, unsigned idx)
+{
+	const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx];
+	struct clk_init_data clk_init;
+	struct ingenic_clk *ingenic_clk = NULL;
+	struct clk *clk, *parent;
+	const char *parent_names[4];
+	unsigned caps, i, num_possible;
+	int err = -EINVAL;
+
+	BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names));
+
+	if (clk_info->type == CGU_CLK_EXT) {
+		clk = of_clk_get_by_name(cgu->np, clk_info->name);
+		if (IS_ERR(clk)) {
+			pr_err("%s: no external clock '%s' provided\n",
+			       __func__, clk_info->name);
+			err = -ENODEV;
+			goto out;
+		}
+		err = clk_register_clkdev(clk, clk_info->name, NULL);
+		if (err) {
+			clk_put(clk);
+			goto out;
+		}
+		cgu->clocks.clks[idx] = clk;
+		return 0;
+	}
+
+	if (!clk_info->type) {
+		pr_err("%s: no clock type specified for '%s'\n", __func__,
+		       clk_info->name);
+		goto out;
+	}
+
+	ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL);
+	if (!ingenic_clk) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	ingenic_clk->hw.init = &clk_init;
+	ingenic_clk->cgu = cgu;
+	ingenic_clk->idx = idx;
+
+	clk_init.name = clk_info->name;
+	clk_init.flags = 0;
+	clk_init.parent_names = parent_names;
+
+	caps = clk_info->type;
+
+	if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
+		clk_init.num_parents = 0;
+
+		if (caps & CGU_CLK_MUX)
+			num_possible = 1 << clk_info->mux.bits;
+		else
+			num_possible = ARRAY_SIZE(clk_info->parents);
+
+		for (i = 0; i < num_possible; i++) {
+			if (clk_info->parents[i] == -1)
+				continue;
+
+			parent = cgu->clocks.clks[clk_info->parents[i]];
+			parent_names[clk_init.num_parents] =
+				__clk_get_name(parent);
+			clk_init.num_parents++;
+		}
+
+		BUG_ON(!clk_init.num_parents);
+		BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names));
+	} else {
+		BUG_ON(clk_info->parents[0] == -1);
+		clk_init.num_parents = 1;
+		parent = cgu->clocks.clks[clk_info->parents[0]];
+		parent_names[0] = __clk_get_name(parent);
+	}
+
+	if (caps & CGU_CLK_CUSTOM) {
+		clk_init.ops = clk_info->custom.clk_ops;
+
+		caps &= ~CGU_CLK_CUSTOM;
+
+		if (caps) {
+			pr_err("%s: custom clock may not be combined with type 0x%x\n",
+			       __func__, caps);
+			goto out;
+		}
+	} else if (caps & CGU_CLK_PLL) {
+		clk_init.ops = &ingenic_pll_ops;
+
+		caps &= ~CGU_CLK_PLL;
+
+		if (caps) {
+			pr_err("%s: PLL may not be combined with type 0x%x\n",
+			       __func__, caps);
+			goto out;
+		}
+	} else {
+		clk_init.ops = &ingenic_clk_ops;
+	}
+
+	/* nothing to do for gates or fixed dividers */
+	caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV);
+
+	if (caps & CGU_CLK_MUX) {
+		if (!(caps & CGU_CLK_MUX_GLITCHFREE))
+			clk_init.flags |= CLK_SET_PARENT_GATE;
+
+		caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE);
+	}
+
+	if (caps & CGU_CLK_DIV) {
+		caps &= ~CGU_CLK_DIV;
+	} else {
+		/* pass rate changes to the parent clock */
+		clk_init.flags |= CLK_SET_RATE_PARENT;
+	}
+
+	if (caps) {
+		pr_err("%s: unknown clock type 0x%x\n", __func__, caps);
+		goto out;
+	}
+
+	clk = clk_register(NULL, &ingenic_clk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register clock '%s'\n", __func__,
+		       clk_info->name);
+		err = PTR_ERR(clk);
+		goto out;
+	}
+
+	err = clk_register_clkdev(clk, clk_info->name, NULL);
+	if (err)
+		goto out;
+
+	cgu->clocks.clks[idx] = clk;
+out:
+	if (err)
+		kfree(ingenic_clk);
+	return err;
+}
+
+struct ingenic_cgu *
+ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
+		unsigned num_clocks, struct device_node *np)
+{
+	struct ingenic_cgu *cgu;
+
+	cgu = kzalloc(sizeof(*cgu), GFP_KERNEL);
+	if (!cgu)
+		goto err_out;
+
+	cgu->base = of_iomap(np, 0);
+	if (!cgu->base) {
+		pr_err("%s: failed to map CGU registers\n", __func__);
+		goto err_out_free;
+	}
+
+	cgu->np = np;
+	cgu->clock_info = clock_info;
+	cgu->clocks.clk_num = num_clocks;
+
+	spin_lock_init(&cgu->divmux_lock);
+	spin_lock_init(&cgu->power_lock);
+	spin_lock_init(&cgu->pll_lock);
+
+	return cgu;
+
+err_out_free:
+	kfree(cgu);
+err_out:
+	return NULL;
+}
+
+int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu)
+{
+	unsigned i;
+	int err;
+
+	cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *),
+				   GFP_KERNEL);
+	if (!cgu->clocks.clks) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	for (i = 0; i < cgu->clocks.clk_num; i++) {
+		err = register_clock(cgu, i);
+		if (err)
+			goto err_out_unregister;
+	}
+
+	err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get,
+				  &cgu->clocks);
+	if (err)
+		goto err_out_unregister;
+
+	return 0;
+
+err_out_unregister:
+	if (cgu) {
+		for (i = 0; i < cgu->clocks.clk_num; i++) {
+			if (!cgu->clocks.clks[i])
+				continue;
+			if (cgu->clock_info[i].type & CGU_CLK_EXT)
+				clk_put(cgu->clocks.clks[i]);
+			else
+				clk_unregister(cgu->clocks.clks[i]);
+		}
+		kfree(cgu->clocks.clks);
+	}
+err_out:
+	return err;
+}
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
new file mode 100644
index 0000000..47e0552
--- /dev/null
+++ b/drivers/clk/ingenic/cgu.h
@@ -0,0 +1,223 @@
+/*
+ * Ingenic SoC CGU driver
+ *
+ * Copyright (c) 2013-2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRIVERS_CLK_INGENIC_CGU_H__
+#define __DRIVERS_CLK_INGENIC_CGU_H__
+
+#include <linux/of.h>
+#include <linux/spinlock.h>
+
+/**
+ * struct ingenic_cgu_pll_info - information about a PLL
+ * @reg: the offset of the PLL's control register within the CGU
+ * @m_shift: the number of bits to shift the multiplier value by (ie. the
+ *           index of the lowest bit of the multiplier value in the PLL's
+ *           control register)
+ * @m_bits: the size of the multiplier field in bits
+ * @m_offset: the multiplier value which encodes to 0 in the PLL's control
+ *            register
+ * @n_shift: the number of bits to shift the divider value by (ie. the
+ *           index of the lowest bit of the divider value in the PLL's
+ *           control register)
+ * @n_bits: the size of the divider field in bits
+ * @n_offset: the divider value which encodes to 0 in the PLL's control
+ *            register
+ * @od_shift: the number of bits to shift the post-VCO divider value by (ie.
+ *            the index of the lowest bit of the post-VCO divider value in
+ *            the PLL's control register)
+ * @od_bits: the size of the post-VCO divider field in bits
+ * @od_max: the maximum post-VCO divider value
+ * @od_encoding: a pointer to an array mapping post-VCO divider values to
+ *               their encoded values in the PLL control register, or -1 for
+ *               unsupported values
+ * @bypass_bit: the index of the bypass bit in the PLL control register
+ * @enable_bit: the index of the enable bit in the PLL control register
+ * @stable_bit: the index of the stable bit in the PLL control register
+ */
+struct ingenic_cgu_pll_info {
+	unsigned reg;
+	unsigned m_shift, m_bits, m_offset;
+	unsigned n_shift, n_bits, n_offset;
+	unsigned od_shift, od_bits, od_max;
+	const s8 *od_encoding;
+	unsigned bypass_bit;
+	unsigned enable_bit;
+	unsigned stable_bit;
+};
+
+/**
+ * struct ingenic_cgu_mux_info - information about a clock mux
+ * @reg: offset of the mux control register within the CGU
+ * @shift: number of bits to shift the mux value by (ie. the index of
+ *         the lowest bit of the mux value within its control register)
+ * @bits: the size of the mux value in bits
+ */
+struct ingenic_cgu_mux_info {
+	unsigned reg;
+	unsigned shift:5;
+	unsigned bits:5;
+};
+
+/**
+ * struct ingenic_cgu_div_info - information about a divider
+ * @reg: offset of the divider control register within the CGU
+ * @shift: number of bits to shift the divide value by (ie. the index of
+ *         the lowest bit of the divide value within its control register)
+ * @bits: the size of the divide value in bits
+ * @ce_bit: the index of the change enable bit within reg, or -1 is there
+ *          isn't one
+ * @busy_bit: the index of the busy bit within reg, or -1 is there isn't one
+ * @stop_bit: the index of the stop bit within reg, or -1 is there isn't one
+ */
+struct ingenic_cgu_div_info {
+	unsigned reg;
+	unsigned shift:5;
+	unsigned bits:5;
+	int ce_bit:6;
+	int busy_bit:6;
+	int stop_bit:6;
+};
+
+/**
+ * struct ingenic_cgu_fixdiv_info - information about a fixed divider
+ * @div: the divider applied to the parent clock
+ */
+struct ingenic_cgu_fixdiv_info {
+	unsigned div;
+};
+
+/**
+ * struct ingenic_cgu_gate_info - information about a clock gate
+ * @reg: offset of the gate control register within the CGU
+ * @bit: offset of the bit in the register that controls the gate
+ */
+struct ingenic_cgu_gate_info {
+	unsigned reg;
+	unsigned bit:5;
+};
+
+/**
+ * struct ingenic_cgu_custom_info - information about a custom (SoC) clock
+ */
+struct ingenic_cgu_custom_info {
+	struct clk_ops *clk_ops;
+};
+
+/**
+ * struct ingenic_cgu_clk_info - information about a clock
+ * @name: name of the clock
+ * @type: a bitmask formed from CGU_CLK_* values
+ * @parents: an array of the indices of potential parents of this clock
+ *           within the clock_info array of the CGU, or -1 in entries
+ *           which correspond to no valid parent
+ * @pll: information valid if type includes CGU_CLK_PLL
+ * @gate: information valid if type includes CGU_CLK_GATE
+ * @mux: information valid if type includes CGU_CLK_MUX
+ * @div: information valid if type includes CGU_CLK_DIV
+ */
+struct ingenic_cgu_clk_info {
+	const char *name;
+
+	enum {
+		CGU_CLK_NONE		= 0,
+		CGU_CLK_EXT		= (1 << 0),
+		CGU_CLK_PLL		= (1 << 1),
+		CGU_CLK_GATE		= (1 << 2),
+		CGU_CLK_MUX		= (1 << 3),
+		CGU_CLK_MUX_GLITCHFREE	= (1 << 4),
+		CGU_CLK_DIV		= (1 << 5),
+		CGU_CLK_FIXDIV		= (1 << 6),
+		CGU_CLK_CUSTOM		= (1 << 7),
+	} type;
+
+	int parents[4];
+
+	union {
+		struct ingenic_cgu_pll_info pll;
+
+		struct {
+			struct ingenic_cgu_gate_info gate;
+			struct ingenic_cgu_mux_info mux;
+			struct ingenic_cgu_div_info div;
+			struct ingenic_cgu_fixdiv_info fixdiv;
+		};
+
+		struct ingenic_cgu_custom_info custom;
+	};
+};
+
+/**
+ * struct ingenic_cgu - data about the CGU
+ * @np: the device tree node that caused the CGU to be probed
+ * @base: the ioremap'ed base address of the CGU registers
+ * @clock_info: an array containing information about implemented clocks
+ * @clocks: used to provide clocks to DT, allows lookup of struct clk*
+ * @gate_lock: lock to be held whilst (un)gating a clock
+ * @divmux_lock: lock to be held whilst re-muxing of rate-changing a clock
+ */
+struct ingenic_cgu {
+	struct device_node *np;
+	void __iomem *base;
+
+	const struct ingenic_cgu_clk_info *clock_info;
+	struct clk_onecell_data clocks;
+
+	spinlock_t divmux_lock;		/* must be held when changing a divide
+					   or re-muxing a clock */
+	spinlock_t power_lock;		/* must be held when changing a power
+					   manager register */
+	spinlock_t pll_lock;		/* must be held when changing a PLL
+					   control register */
+};
+
+/**
+ * struct ingenic_clk - private data for a clock
+ * @hw: see Documentation/clk.txt
+ * @cgu: a pointer to the CGU data
+ * @idx: the index of this clock in cgu->clock_info
+ */
+struct ingenic_clk {
+	struct clk_hw hw;
+	struct ingenic_cgu *cgu;
+	unsigned idx;
+};
+
+#define to_ingenic_clk(_hw) container_of(_hw, struct ingenic_clk, hw)
+
+/**
+ * ingenic_cgu_new - create a new CGU instance
+ * @clock_info: an array of clock information structures describing the clocks
+ *              which are implemented by the CGU
+ * @num_clocks: the number of entries in clock_info
+ * @np: the device tree node which causes this CGU to be probed
+ *
+ * Returns an opaque pointer to the CGU instance if initialisation & clock
+ * registration is successful, otherwise NULL.
+ */
+struct ingenic_cgu *
+ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
+		unsigned num_clocks, struct device_node *np);
+
+/**
+ * ingenic_cgu_register_clocks - Registers the clocks
+ * @cgu: pointer to cgu data
+ *
+ * Returns 1 on success and -EINVAL if unsuccesful.
+ */
+int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu);
+
+#endif /* __DRIVERS_CLK_INGENIC_CGU_H__ */
-- 
2.3.5

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

* [PATCH v3 26/37] MIPS,clk: migrate JZ4740 to common clock framework
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

Migrate the JZ4740 & the qi_lb60 board to use common clock framework
via the new Ingenic SoC CGU driver.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Co-authored-by: Paul Cercueil <paul@crapouillou.net>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Handle gating the "udc" clock.

Changes in v2:
  - None.
---
 arch/mips/Kconfig                      |   2 +-
 arch/mips/boot/dts/ingenic/jz4740.dtsi |  23 +
 arch/mips/boot/dts/ingenic/qi_lb60.dts |   4 +
 arch/mips/jz4740/Makefile              |   2 -
 arch/mips/jz4740/board-qi_lb60.c       |   5 -
 arch/mips/jz4740/clock-debugfs.c       | 108 -----
 arch/mips/jz4740/clock.c               | 801 +--------------------------------
 arch/mips/jz4740/clock.h               |  53 +--
 arch/mips/jz4740/time.c                |   2 +
 drivers/clk/ingenic/Makefile           |   1 +
 drivers/clk/ingenic/jz4740-cgu.c       | 220 +++++++++
 11 files changed, 253 insertions(+), 968 deletions(-)
 delete mode 100644 arch/mips/jz4740/clock-debugfs.c
 create mode 100644 drivers/clk/ingenic/jz4740-cgu.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 741e364..e3c859c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -297,7 +297,7 @@ config MACH_INGENIC
 	select IRQ_CPU
 	select ARCH_REQUIRE_GPIOLIB
 	select SYS_HAS_EARLY_PRINTK
-	select HAVE_CLK
+	select COMMON_CLK
 	select GENERIC_IRQ_CHIP
 	select BUILTIN_DTB
 	select USE_OF
diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index 3841024..ef679b4 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -1,3 +1,5 @@
+#include <dt-bindings/clock/jz4740-cgu.h>
+
 / {
 	#address-cells = <1>;
 	#size-cells = <1>;
@@ -20,4 +22,25 @@
 		interrupt-parent = <&cpuintc>;
 		interrupts = <2>;
 	};
+
+	ext: ext {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+	};
+
+	rtc: rtc {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	cgu: jz4740-cgu@10000000 {
+		compatible = "ingenic,jz4740-cgu";
+		reg = <0x10000000 0x100>;
+
+		clocks = <&ext>, <&rtc>;
+		clock-names = "ext", "rtc";
+
+		#clock-cells = <1>;
+	};
 };
diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts
index 0c0f639..106d13c 100644
--- a/arch/mips/boot/dts/ingenic/qi_lb60.dts
+++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -5,3 +5,7 @@
 / {
 	compatible = "qi,lb60", "ingenic,jz4740";
 };
+
+&ext {
+	clock-frequency = <12000000>;
+};
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 6cf5dd4..fdb12efc 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -7,8 +7,6 @@
 obj-y += prom.o time.o reset.o setup.o \
 	gpio.o clock.o platform.o timer.o serial.o
 
-obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
-
 # board specific support
 
 obj-$(CONFIG_JZ4740_QI_LB60)	+= board-qi_lb60.o
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 9dd051e..21b034c 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -497,11 +497,6 @@ static int __init qi_lb60_init_platform_devices(void)
 
 }
 
-struct jz4740_clock_board_data jz4740_clock_bdata = {
-	.ext_rate = 12000000,
-	.rtc_rate = 32768,
-};
-
 static __init int board_avt2(char *str)
 {
 	qi_lb60_mmc_pdata.card_detect_active_low = 1;
diff --git a/arch/mips/jz4740/clock-debugfs.c b/arch/mips/jz4740/clock-debugfs.c
deleted file mode 100644
index 325422d0..0000000
--- a/arch/mips/jz4740/clock-debugfs.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 SoC clock support debugfs entries
- *
- *  This program 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.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>
-
-#include <asm/mach-jz4740/clock.h>
-#include "clock.h"
-
-static struct dentry *jz4740_clock_debugfs;
-
-static int jz4740_clock_debugfs_show_enabled(void *data, uint64_t *value)
-{
-	struct clk *clk = data;
-	*value = clk_is_enabled(clk);
-
-	return 0;
-}
-
-static int jz4740_clock_debugfs_set_enabled(void *data, uint64_t value)
-{
-	struct clk *clk = data;
-
-	if (value)
-		return clk_enable(clk);
-	else
-		clk_disable(clk);
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_enabled,
-	jz4740_clock_debugfs_show_enabled,
-	jz4740_clock_debugfs_set_enabled,
-	"%llu\n");
-
-static int jz4740_clock_debugfs_show_rate(void *data, uint64_t *value)
-{
-	struct clk *clk = data;
-	*value = clk_get_rate(clk);
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_rate,
-	jz4740_clock_debugfs_show_rate,
-	NULL,
-	"%llu\n");
-
-void jz4740_clock_debugfs_add_clk(struct clk *clk)
-{
-	if (!jz4740_clock_debugfs)
-		return;
-
-	clk->debugfs_entry = debugfs_create_dir(clk->name, jz4740_clock_debugfs);
-	debugfs_create_file("rate", S_IWUGO | S_IRUGO, clk->debugfs_entry, clk,
-				&jz4740_clock_debugfs_ops_rate);
-	debugfs_create_file("enabled", S_IRUGO, clk->debugfs_entry, clk,
-				&jz4740_clock_debugfs_ops_enabled);
-
-	if (clk->parent) {
-		char parent_path[100];
-		snprintf(parent_path, 100, "../%s", clk->parent->name);
-		clk->debugfs_parent_entry = debugfs_create_symlink("parent",
-						clk->debugfs_entry,
-						parent_path);
-	}
-}
-
-/* TODO: Locking */
-void jz4740_clock_debugfs_update_parent(struct clk *clk)
-{
-	debugfs_remove(clk->debugfs_parent_entry);
-
-	if (clk->parent) {
-		char parent_path[100];
-		snprintf(parent_path, 100, "../%s", clk->parent->name);
-		clk->debugfs_parent_entry = debugfs_create_symlink("parent",
-						clk->debugfs_entry,
-						parent_path);
-	} else {
-		clk->debugfs_parent_entry = NULL;
-	}
-}
-
-void jz4740_clock_debugfs_init(void)
-{
-	jz4740_clock_debugfs = debugfs_create_dir("jz4740-clock", NULL);
-	if (IS_ERR(jz4740_clock_debugfs))
-		jz4740_clock_debugfs = NULL;
-}
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index c257073..dedee7c 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -27,820 +28,44 @@
 
 #include "clock.h"
 
-#define JZ_REG_CLOCK_CTRL	0x00
 #define JZ_REG_CLOCK_LOW_POWER	0x04
 #define JZ_REG_CLOCK_PLL	0x10
 #define JZ_REG_CLOCK_GATE	0x20
-#define JZ_REG_CLOCK_SLEEP_CTRL 0x24
-#define JZ_REG_CLOCK_I2S	0x60
-#define JZ_REG_CLOCK_LCD	0x64
-#define JZ_REG_CLOCK_MMC	0x68
-#define JZ_REG_CLOCK_UHC	0x6C
-#define JZ_REG_CLOCK_SPI	0x74
-
-#define JZ_CLOCK_CTRL_I2S_SRC_PLL	BIT(31)
-#define JZ_CLOCK_CTRL_KO_ENABLE		BIT(30)
-#define JZ_CLOCK_CTRL_UDC_SRC_PLL	BIT(29)
-#define JZ_CLOCK_CTRL_UDIV_MASK		0x1f800000
-#define JZ_CLOCK_CTRL_CHANGE_ENABLE	BIT(22)
-#define JZ_CLOCK_CTRL_PLL_HALF		BIT(21)
-#define JZ_CLOCK_CTRL_LDIV_MASK		0x001f0000
-#define JZ_CLOCK_CTRL_UDIV_OFFSET	23
-#define JZ_CLOCK_CTRL_LDIV_OFFSET	16
-#define JZ_CLOCK_CTRL_MDIV_OFFSET	12
-#define JZ_CLOCK_CTRL_PDIV_OFFSET	 8
-#define JZ_CLOCK_CTRL_HDIV_OFFSET	 4
-#define JZ_CLOCK_CTRL_CDIV_OFFSET	 0
 
 #define JZ_CLOCK_GATE_UART0	BIT(0)
 #define JZ_CLOCK_GATE_TCU	BIT(1)
-#define JZ_CLOCK_GATE_RTC	BIT(2)
-#define JZ_CLOCK_GATE_I2C	BIT(3)
-#define JZ_CLOCK_GATE_SPI	BIT(4)
-#define JZ_CLOCK_GATE_AIC	BIT(5)
-#define JZ_CLOCK_GATE_I2S	BIT(6)
-#define JZ_CLOCK_GATE_MMC	BIT(7)
-#define JZ_CLOCK_GATE_ADC	BIT(8)
-#define JZ_CLOCK_GATE_CIM	BIT(9)
-#define JZ_CLOCK_GATE_LCD	BIT(10)
 #define JZ_CLOCK_GATE_UDC	BIT(11)
 #define JZ_CLOCK_GATE_DMAC	BIT(12)
-#define JZ_CLOCK_GATE_IPU	BIT(13)
-#define JZ_CLOCK_GATE_UHC	BIT(14)
-#define JZ_CLOCK_GATE_UART1	BIT(15)
-
-#define JZ_CLOCK_I2S_DIV_MASK		0x01ff
-
-#define JZ_CLOCK_LCD_DIV_MASK		0x01ff
-
-#define JZ_CLOCK_MMC_DIV_MASK		0x001f
 
-#define JZ_CLOCK_UHC_DIV_MASK		0x000f
-
-#define JZ_CLOCK_SPI_SRC_PLL		BIT(31)
-#define JZ_CLOCK_SPI_DIV_MASK		0x000f
-
-#define JZ_CLOCK_PLL_M_MASK		0x01ff
-#define JZ_CLOCK_PLL_N_MASK		0x001f
-#define JZ_CLOCK_PLL_OD_MASK		0x0003
 #define JZ_CLOCK_PLL_STABLE		BIT(10)
-#define JZ_CLOCK_PLL_BYPASS		BIT(9)
 #define JZ_CLOCK_PLL_ENABLED		BIT(8)
-#define JZ_CLOCK_PLL_STABLIZE_MASK	0x000f
-#define JZ_CLOCK_PLL_M_OFFSET		23
-#define JZ_CLOCK_PLL_N_OFFSET		18
-#define JZ_CLOCK_PLL_OD_OFFSET		16
 
 #define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
 #define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
 
-#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
-#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
-
 static void __iomem *jz_clock_base;
-static spinlock_t jz_clock_lock;
-static LIST_HEAD(jz_clocks);
-
-struct main_clk {
-	struct clk clk;
-	uint32_t div_offset;
-};
-
-struct divided_clk {
-	struct clk clk;
-	uint32_t reg;
-	uint32_t mask;
-};
-
-struct static_clk {
-	struct clk clk;
-	unsigned long rate;
-};
 
 static uint32_t jz_clk_reg_read(int reg)
 {
 	return readl(jz_clock_base + reg);
 }
 
-static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask)
-{
-	uint32_t val2;
-
-	spin_lock(&jz_clock_lock);
-	val2 = readl(jz_clock_base + reg);
-	val2 &= ~mask;
-	val2 |= val;
-	writel(val2, jz_clock_base + reg);
-	spin_unlock(&jz_clock_lock);
-}
-
 static void jz_clk_reg_set_bits(int reg, uint32_t mask)
 {
 	uint32_t val;
 
-	spin_lock(&jz_clock_lock);
 	val = readl(jz_clock_base + reg);
 	val |= mask;
 	writel(val, jz_clock_base + reg);
-	spin_unlock(&jz_clock_lock);
 }
 
 static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
 {
 	uint32_t val;
 
-	spin_lock(&jz_clock_lock);
 	val = readl(jz_clock_base + reg);
 	val &= ~mask;
 	writel(val, jz_clock_base + reg);
-	spin_unlock(&jz_clock_lock);
-}
-
-static int jz_clk_enable_gating(struct clk *clk)
-{
-	if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
-		return -EINVAL;
-
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
-	return 0;
-}
-
-static int jz_clk_disable_gating(struct clk *clk)
-{
-	if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
-		return -EINVAL;
-
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
-	return 0;
-}
-
-static int jz_clk_is_enabled_gating(struct clk *clk)
-{
-	if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
-		return 1;
-
-	return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit);
-}
-
-static unsigned long jz_clk_static_get_rate(struct clk *clk)
-{
-	return ((struct static_clk *)clk)->rate;
-}
-
-static int jz_clk_ko_enable(struct clk *clk)
-{
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
-	return 0;
-}
-
-static int jz_clk_ko_disable(struct clk *clk)
-{
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
-	return 0;
-}
-
-static int jz_clk_ko_is_enabled(struct clk *clk)
-{
-	return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
-}
-
-static const int pllno[] = {1, 2, 2, 4};
-
-static unsigned long jz_clk_pll_get_rate(struct clk *clk)
-{
-	uint32_t val;
-	int m;
-	int n;
-	int od;
-
-	val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
-
-	if (val & JZ_CLOCK_PLL_BYPASS)
-		return clk_get_rate(clk->parent);
-
-	m = ((val >> 23) & 0x1ff) + 2;
-	n = ((val >> 18) & 0x1f) + 2;
-	od = (val >> 16) & 0x3;
-
-	return ((clk_get_rate(clk->parent) / n) * m) / pllno[od];
-}
-
-static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
-{
-	uint32_t reg;
-
-	reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-	if (reg & JZ_CLOCK_CTRL_PLL_HALF)
-		return jz_clk_pll_get_rate(clk->parent);
-	return jz_clk_pll_get_rate(clk->parent) >> 1;
-}
-
-static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
-
-static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
-	int div;
-
-	div = parent_rate / rate;
-	if (div > 32)
-		return parent_rate / 32;
-	else if (div < 1)
-		return parent_rate;
-
-	div &= (0x3 << (ffs(div) - 1));
-
-	return parent_rate / div;
-}
-
-static unsigned long jz_clk_main_get_rate(struct clk *clk)
-{
-	struct main_clk *mclk = (struct main_clk *)clk;
-	uint32_t div;
-
-	div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-
-	div >>= mclk->div_offset;
-	div &= 0xf;
-
-	if (div >= ARRAY_SIZE(jz_clk_main_divs))
-		div = ARRAY_SIZE(jz_clk_main_divs) - 1;
-
-	return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div];
-}
-
-static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
-{
-	struct main_clk *mclk = (struct main_clk *)clk;
-	int i;
-	int div;
-	unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
-
-	rate = jz_clk_main_round_rate(clk, rate);
-
-	div = parent_rate / rate;
-
-	i = (ffs(div) - 1) << 1;
-	if (i > 0 && !(div & BIT(i-1)))
-		i -= 1;
-
-	jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset,
-				0xf << mclk->div_offset);
-
-	return 0;
-}
-
-static struct clk_ops jz_clk_static_ops = {
-	.get_rate = jz_clk_static_get_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct static_clk jz_clk_ext = {
-	.clk = {
-		.name = "ext",
-		.gate_bit = JZ4740_CLK_NOT_GATED,
-		.ops = &jz_clk_static_ops,
-	},
-};
-
-static struct clk_ops jz_clk_pll_ops = {
-	.get_rate = jz_clk_pll_get_rate,
-};
-
-static struct clk jz_clk_pll = {
-	.name = "pll",
-	.parent = &jz_clk_ext.clk,
-	.ops = &jz_clk_pll_ops,
-};
-
-static struct clk_ops jz_clk_pll_half_ops = {
-	.get_rate = jz_clk_pll_half_get_rate,
-};
-
-static struct clk jz_clk_pll_half = {
-	.name = "pll half",
-	.parent = &jz_clk_pll,
-	.ops = &jz_clk_pll_half_ops,
-};
-
-static const struct clk_ops jz_clk_main_ops = {
-	.get_rate = jz_clk_main_get_rate,
-	.set_rate = jz_clk_main_set_rate,
-	.round_rate = jz_clk_main_round_rate,
-};
-
-static struct main_clk jz_clk_cpu = {
-	.clk = {
-		.name = "cclk",
-		.parent = &jz_clk_pll,
-		.ops = &jz_clk_main_ops,
-	},
-	.div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
-};
-
-static struct main_clk jz_clk_memory = {
-	.clk = {
-		.name = "mclk",
-		.parent = &jz_clk_pll,
-		.ops = &jz_clk_main_ops,
-	},
-	.div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
-};
-
-static struct main_clk jz_clk_high_speed_peripheral = {
-	.clk = {
-		.name = "hclk",
-		.parent = &jz_clk_pll,
-		.ops = &jz_clk_main_ops,
-	},
-	.div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
-};
-
-
-static struct main_clk jz_clk_low_speed_peripheral = {
-	.clk = {
-		.name = "pclk",
-		.parent = &jz_clk_pll,
-		.ops = &jz_clk_main_ops,
-	},
-	.div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
-};
-
-static const struct clk_ops jz_clk_ko_ops = {
-	.enable = jz_clk_ko_enable,
-	.disable = jz_clk_ko_disable,
-	.is_enabled = jz_clk_ko_is_enabled,
-};
-
-static struct clk jz_clk_ko = {
-	.name = "cko",
-	.parent = &jz_clk_memory.clk,
-	.ops = &jz_clk_ko_ops,
-};
-
-static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
-{
-	if (parent == &jz_clk_pll)
-		jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
-	else if (parent == &jz_clk_ext.clk)
-		jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	return 0;
-}
-
-static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
-{
-	if (parent == &jz_clk_pll_half)
-		jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
-	else if (parent == &jz_clk_ext.clk)
-		jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	return 0;
-}
-
-static int jz_clk_udc_enable(struct clk *clk)
-{
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL,
-			JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
-
-	return 0;
-}
-
-static int jz_clk_udc_disable(struct clk *clk)
-{
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL,
-			JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
-
-	return 0;
-}
-
-static int jz_clk_udc_is_enabled(struct clk *clk)
-{
-	return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) &
-			JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
-}
-
-static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
-{
-	if (parent == &jz_clk_pll_half)
-		jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
-	else if (parent == &jz_clk_ext.clk)
-		jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	return 0;
-}
-
-static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate)
-{
-	int div;
-
-	if (clk->parent == &jz_clk_ext.clk)
-		return -EINVAL;
-
-	div = clk_get_rate(clk->parent) / rate - 1;
-
-	if (div < 0)
-		div = 0;
-	else if (div > 63)
-		div = 63;
-
-	jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET,
-				JZ_CLOCK_CTRL_UDIV_MASK);
-	return 0;
-}
-
-static unsigned long jz_clk_udc_get_rate(struct clk *clk)
-{
-	int div;
-
-	if (clk->parent == &jz_clk_ext.clk)
-		return clk_get_rate(clk->parent);
-
-	div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK);
-	div >>= JZ_CLOCK_CTRL_UDIV_OFFSET;
-	div += 1;
-
-	return clk_get_rate(clk->parent) / div;
-}
-
-static unsigned long jz_clk_divided_get_rate(struct clk *clk)
-{
-	struct divided_clk *dclk = (struct divided_clk *)clk;
-	int div;
-
-	if (clk->parent == &jz_clk_ext.clk)
-		return clk_get_rate(clk->parent);
-
-	div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1;
-
-	return clk_get_rate(clk->parent) / div;
-}
-
-static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate)
-{
-	struct divided_clk *dclk = (struct divided_clk *)clk;
-	int div;
-
-	if (clk->parent == &jz_clk_ext.clk)
-		return -EINVAL;
-
-	div = clk_get_rate(clk->parent) / rate - 1;
-
-	if (div < 0)
-		div = 0;
-	else if (div > dclk->mask)
-		div = dclk->mask;
-
-	jz_clk_reg_write_mask(dclk->reg, div, dclk->mask);
-
-	return 0;
-}
-
-static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate)
-{
-	int div;
-	unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent);
-
-	if (rate > 150000000)
-		return 150000000;
-
-	div = parent_rate / rate;
-	if (div < 1)
-		div = 1;
-	else if (div > 32)
-		div = 32;
-
-	return parent_rate / div;
-}
-
-static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate)
-{
-	int div;
-
-	if (rate > 150000000)
-		return -EINVAL;
-
-	div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1;
-	if (div < 0)
-		div = 0;
-	else if (div > 31)
-		div = 31;
-
-	jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET,
-				JZ_CLOCK_CTRL_LDIV_MASK);
-
-	return 0;
-}
-
-static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
-{
-	int div;
-
-	div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK;
-	div >>= JZ_CLOCK_CTRL_LDIV_OFFSET;
-
-	return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
-}
-
-static const struct clk_ops jz_clk_ops_ld = {
-	.set_rate = jz_clk_ldclk_set_rate,
-	.get_rate = jz_clk_ldclk_get_rate,
-	.round_rate = jz_clk_ldclk_round_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct clk jz_clk_ld = {
-	.name = "lcd",
-	.gate_bit = JZ_CLOCK_GATE_LCD,
-	.parent = &jz_clk_pll_half,
-	.ops = &jz_clk_ops_ld,
-};
-
-static const struct clk_ops jz_clk_i2s_ops = {
-	.set_rate = jz_clk_divided_set_rate,
-	.get_rate = jz_clk_divided_get_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-	.set_parent = jz_clk_i2s_set_parent,
-};
-
-static const struct clk_ops jz_clk_spi_ops = {
-	.set_rate = jz_clk_divided_set_rate,
-	.get_rate = jz_clk_divided_get_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-	.set_parent = jz_clk_spi_set_parent,
-};
-
-static const struct clk_ops jz_clk_divided_ops = {
-	.set_rate = jz_clk_divided_set_rate,
-	.get_rate = jz_clk_divided_get_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct divided_clk jz4740_clock_divided_clks[] = {
-	[0] = {
-		.clk = {
-			.name = "i2s",
-			.parent = &jz_clk_ext.clk,
-			.gate_bit = JZ_CLOCK_GATE_I2S,
-			.ops = &jz_clk_i2s_ops,
-		},
-		.reg = JZ_REG_CLOCK_I2S,
-		.mask = JZ_CLOCK_I2S_DIV_MASK,
-	},
-	[1] = {
-		.clk = {
-			.name = "spi",
-			.parent = &jz_clk_ext.clk,
-			.gate_bit = JZ_CLOCK_GATE_SPI,
-			.ops = &jz_clk_spi_ops,
-		},
-		.reg = JZ_REG_CLOCK_SPI,
-		.mask = JZ_CLOCK_SPI_DIV_MASK,
-	},
-	[2] = {
-		.clk = {
-			.name = "lcd_pclk",
-			.parent = &jz_clk_pll_half,
-			.gate_bit = JZ4740_CLK_NOT_GATED,
-			.ops = &jz_clk_divided_ops,
-		},
-		.reg = JZ_REG_CLOCK_LCD,
-		.mask = JZ_CLOCK_LCD_DIV_MASK,
-	},
-	[3] = {
-		.clk = {
-			.name = "mmc",
-			.parent = &jz_clk_pll_half,
-			.gate_bit = JZ_CLOCK_GATE_MMC,
-			.ops = &jz_clk_divided_ops,
-		},
-		.reg = JZ_REG_CLOCK_MMC,
-		.mask = JZ_CLOCK_MMC_DIV_MASK,
-	},
-	[4] = {
-		.clk = {
-			.name = "uhc",
-			.parent = &jz_clk_pll_half,
-			.gate_bit = JZ_CLOCK_GATE_UHC,
-			.ops = &jz_clk_divided_ops,
-		},
-		.reg = JZ_REG_CLOCK_UHC,
-		.mask = JZ_CLOCK_UHC_DIV_MASK,
-	},
-};
-
-static const struct clk_ops jz_clk_udc_ops = {
-	.set_parent = jz_clk_udc_set_parent,
-	.set_rate = jz_clk_udc_set_rate,
-	.get_rate = jz_clk_udc_get_rate,
-	.enable = jz_clk_udc_enable,
-	.disable = jz_clk_udc_disable,
-	.is_enabled = jz_clk_udc_is_enabled,
-};
-
-static const struct clk_ops jz_clk_simple_ops = {
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct clk jz4740_clock_simple_clks[] = {
-	[0] = {
-		.name = "udc",
-		.parent = &jz_clk_ext.clk,
-		.ops = &jz_clk_udc_ops,
-	},
-	[1] = {
-		.name = "uart0",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_UART0,
-		.ops = &jz_clk_simple_ops,
-	},
-	[2] = {
-		.name = "uart1",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_UART1,
-		.ops = &jz_clk_simple_ops,
-	},
-	[3] = {
-		.name = "dma",
-		.parent = &jz_clk_high_speed_peripheral.clk,
-		.gate_bit = JZ_CLOCK_GATE_DMAC,
-		.ops = &jz_clk_simple_ops,
-	},
-	[4] = {
-		.name = "ipu",
-		.parent = &jz_clk_high_speed_peripheral.clk,
-		.gate_bit = JZ_CLOCK_GATE_IPU,
-		.ops = &jz_clk_simple_ops,
-	},
-	[5] = {
-		.name = "adc",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_ADC,
-		.ops = &jz_clk_simple_ops,
-	},
-	[6] = {
-		.name = "i2c",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_I2C,
-		.ops = &jz_clk_simple_ops,
-	},
-	[7] = {
-		.name = "aic",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_AIC,
-		.ops = &jz_clk_simple_ops,
-	},
-};
-
-static struct static_clk jz_clk_rtc = {
-	.clk = {
-		.name = "rtc",
-		.gate_bit = JZ_CLOCK_GATE_RTC,
-		.ops = &jz_clk_static_ops,
-	},
-	.rate = 32768,
-};
-
-int clk_enable(struct clk *clk)
-{
-	if (!clk->ops->enable)
-		return -EINVAL;
-
-	return clk->ops->enable(clk);
-}
-EXPORT_SYMBOL_GPL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-	if (clk->ops->disable)
-		clk->ops->disable(clk);
-}
-EXPORT_SYMBOL_GPL(clk_disable);
-
-int clk_is_enabled(struct clk *clk)
-{
-	if (clk->ops->is_enabled)
-		return clk->ops->is_enabled(clk);
-
-	return 1;
-}
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (clk->ops->get_rate)
-		return clk->ops->get_rate(clk);
-	if (clk->parent)
-		return clk_get_rate(clk->parent);
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(clk_get_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	if (!clk->ops->set_rate)
-		return -EINVAL;
-	return clk->ops->set_rate(clk, rate);
-}
-EXPORT_SYMBOL_GPL(clk_set_rate);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	if (clk->ops->round_rate)
-		return clk->ops->round_rate(clk, rate);
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(clk_round_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	int ret;
-	int enabled;
-
-	if (!clk->ops->set_parent)
-		return -EINVAL;
-
-	enabled = clk_is_enabled(clk);
-	if (enabled)
-		clk_disable(clk);
-	ret = clk->ops->set_parent(clk, parent);
-	if (enabled)
-		clk_enable(clk);
-
-	jz4740_clock_debugfs_update_parent(clk);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(clk_set_parent);
-
-struct clk *clk_get(struct device *dev, const char *name)
-{
-	struct clk *clk;
-
-	list_for_each_entry(clk, &jz_clocks, list) {
-		if (strcmp(clk->name, name) == 0)
-			return clk;
-	}
-	return ERR_PTR(-ENXIO);
-}
-EXPORT_SYMBOL_GPL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL_GPL(clk_put);
-
-static inline void clk_add(struct clk *clk)
-{
-	list_add_tail(&clk->list, &jz_clocks);
-
-	jz4740_clock_debugfs_add_clk(clk);
-}
-
-static void clk_register_clks(void)
-{
-	size_t i;
-
-	clk_add(&jz_clk_ext.clk);
-	clk_add(&jz_clk_pll);
-	clk_add(&jz_clk_pll_half);
-	clk_add(&jz_clk_cpu.clk);
-	clk_add(&jz_clk_high_speed_peripheral.clk);
-	clk_add(&jz_clk_low_speed_peripheral.clk);
-	clk_add(&jz_clk_ko);
-	clk_add(&jz_clk_ld);
-	clk_add(&jz_clk_rtc.clk);
-
-	for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i)
-		clk_add(&jz4740_clock_divided_clks[i].clk);
-
-	for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i)
-		clk_add(&jz4740_clock_simple_clks[i]);
 }
 
 void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
@@ -891,33 +116,9 @@ void jz4740_clock_resume(void)
 
 int jz4740_clock_init(void)
 {
-	uint32_t val;
-
 	jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100);
 	if (!jz_clock_base)
 		return -EBUSY;
 
-	spin_lock_init(&jz_clock_lock);
-
-	jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
-	jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate;
-
-	val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
-
-	if (val & JZ_CLOCK_SPI_SRC_PLL)
-		jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half;
-
-	val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-
-	if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
-		jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half;
-
-	if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
-		jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half;
-
-	jz4740_clock_debugfs_init();
-
-	clk_register_clks();
-
 	return 0;
 }
diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h
index 5d07499..86a3e01 100644
--- a/arch/mips/jz4740/clock.h
+++ b/arch/mips/jz4740/clock.h
@@ -16,61 +16,10 @@
 #ifndef __MIPS_JZ4740_CLOCK_H__
 #define __MIPS_JZ4740_CLOCK_H__
 
+#include <linux/clk.h>
 #include <linux/list.h>
 
-struct jz4740_clock_board_data {
-	unsigned long ext_rate;
-	unsigned long rtc_rate;
-};
-
-extern struct jz4740_clock_board_data jz4740_clock_bdata;
-
 void jz4740_clock_suspend(void);
 void jz4740_clock_resume(void);
 
-struct clk;
-
-struct clk_ops {
-	unsigned long (*get_rate)(struct clk *clk);
-	unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
-	int (*set_rate)(struct clk *clk, unsigned long rate);
-	int (*enable)(struct clk *clk);
-	int (*disable)(struct clk *clk);
-	int (*is_enabled)(struct clk *clk);
-
-	int (*set_parent)(struct clk *clk, struct clk *parent);
-
-};
-
-struct clk {
-	const char *name;
-	struct clk *parent;
-
-	uint32_t gate_bit;
-
-	const struct clk_ops *ops;
-
-	struct list_head list;
-
-#ifdef CONFIG_DEBUG_FS
-	struct dentry *debugfs_entry;
-	struct dentry *debugfs_parent_entry;
-#endif
-
-};
-
-#define JZ4740_CLK_NOT_GATED ((uint32_t)-1)
-
-int clk_is_enabled(struct clk *clk);
-
-#ifdef CONFIG_DEBUG_FS
-void jz4740_clock_debugfs_init(void);
-void jz4740_clock_debugfs_add_clk(struct clk *clk);
-void jz4740_clock_debugfs_update_parent(struct clk *clk);
-#else
-static inline void jz4740_clock_debugfs_init(void) {};
-static inline void jz4740_clock_debugfs_add_clk(struct clk *clk) {};
-static inline void jz4740_clock_debugfs_update_parent(struct clk *clk) {};
-#endif
-
 #endif
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index f66f7f5..be9b0a3 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -14,6 +14,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
@@ -118,6 +119,7 @@ void __init plat_time_init(void)
 	uint16_t ctrl;
 	struct clk *ext_clk;
 
+	of_clk_init(NULL);
 	jz4740_clock_init();
 	jz4740_timer_init();
 
diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index 5ac2fd9..e6db7da 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -1 +1,2 @@
 obj-y				+= cgu.o
+obj-$(CONFIG_MACH_JZ4740)	+= jz4740-cgu.o
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
new file mode 100644
index 0000000..f3c95af
--- /dev/null
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -0,0 +1,220 @@
+/*
+ * Ingenic JZ4740 SoC CGU driver
+ *
+ * Copyright (c) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <dt-bindings/clock/jz4740-cgu.h>
+#include "cgu.h"
+
+/* CGU register offsets */
+#define CGU_REG_CPCCR		0x00
+#define CGU_REG_CPPCR		0x10
+#define CGU_REG_SCR		0x24
+#define CGU_REG_I2SCDR		0x60
+#define CGU_REG_LPCDR		0x64
+#define CGU_REG_MSCCDR		0x68
+#define CGU_REG_UHCCDR		0x6c
+#define CGU_REG_SSICDR		0x74
+
+/* bits within a PLL control register */
+#define PLLCTL_M_SHIFT		23
+#define PLLCTL_M_MASK		(0x1ff << PLLCTL_M_SHIFT)
+#define PLLCTL_N_SHIFT		18
+#define PLLCTL_N_MASK		(0x1f << PLLCTL_N_SHIFT)
+#define PLLCTL_OD_SHIFT		16
+#define PLLCTL_OD_MASK		(0x3 << PLLCTL_OD_SHIFT)
+#define PLLCTL_STABLE		(1 << 10)
+#define PLLCTL_BYPASS		(1 << 9)
+#define PLLCTL_ENABLE		(1 << 8)
+
+static struct ingenic_cgu *cgu;
+
+static const s8 pll_od_encoding[4] = {
+	0x0, 0x1, -1, 0x3,
+};
+
+static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
+
+	/* External clocks */
+
+	[JZ4740_CLK_EXT] = { "ext", CGU_CLK_EXT },
+	[JZ4740_CLK_RTC] = { "rtc", CGU_CLK_EXT },
+
+	[JZ4740_CLK_PLL] = {
+		"pll", CGU_CLK_PLL,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.pll = {
+			.reg = CGU_REG_CPPCR,
+			.m_shift = 23,
+			.m_bits = 9,
+			.m_offset = 2,
+			.n_shift = 18,
+			.n_bits = 5,
+			.n_offset = 2,
+			.od_shift = 16,
+			.od_bits = 2,
+			.od_max = 4,
+			.od_encoding = pll_od_encoding,
+			.stable_bit = 10,
+			.bypass_bit = 9,
+			.enable_bit = 8,
+		},
+	},
+
+	/* Muxes & dividers */
+
+	[JZ4740_CLK_PLL_HALF] = {
+		"pll half", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 21, 1, -1, -1, -1 },
+	},
+
+	[JZ4740_CLK_CCLK] = {
+		"cclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 0, 4, 22, -1, -1 },
+	},
+
+	[JZ4740_CLK_HCLK] = {
+		"hclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 4, 4, 22, -1, -1 },
+	},
+
+	[JZ4740_CLK_PCLK] = {
+		"pclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 8, 4, 22, -1, -1 },
+	},
+
+	[JZ4740_CLK_MCLK] = {
+		"mclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 12, 4, 22, -1, -1 },
+	},
+
+	[JZ4740_CLK_LCD] = {
+		"lcd", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PLL_HALF, -1 },
+		.div = { CGU_REG_CPCCR, 16, 5, 22, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 10 },
+	},
+
+	[JZ4740_CLK_LCD_PCLK] = {
+		"lcd_pclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL_HALF, -1 },
+		.div = { CGU_REG_LPCDR, 0, 11, -1, -1, -1 },
+	},
+
+	[JZ4740_CLK_I2S] = {
+		"i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1 },
+		.mux = { CGU_REG_CPCCR, 31, 1 },
+		.div = { CGU_REG_I2SCDR, 0, 8, -1, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 6 },
+	},
+
+	[JZ4740_CLK_SPI] = {
+		"spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1 },
+		.mux = { CGU_REG_SSICDR, 31, 1 },
+		.div = { CGU_REG_SSICDR, 0, 4, -1, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 4 },
+	},
+
+	[JZ4740_CLK_MMC] = {
+		"mmc", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PLL_HALF, -1 },
+		.div = { CGU_REG_MSCCDR, 0, 5, -1, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 7 },
+	},
+
+	[JZ4740_CLK_UHC] = {
+		"uhc", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PLL_HALF, -1 },
+		.div = { CGU_REG_UHCCDR, 0, 4, -1, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 14 },
+	},
+
+	[JZ4740_CLK_UDC] = {
+		"udc", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1 },
+		.mux = { CGU_REG_CPCCR, 29, 1 },
+		.div = { CGU_REG_CPCCR, 23, 6, -1, -1, -1 },
+		.gate = { CGU_REG_SCR, 6 },
+	},
+
+	/* Gate-only clocks */
+
+	[JZ4740_CLK_UART0] = {
+		"uart0", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 0 },
+	},
+
+	[JZ4740_CLK_UART1] = {
+		"uart1", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 15 },
+	},
+
+	[JZ4740_CLK_DMA] = {
+		"dma", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR, 12 },
+	},
+
+	[JZ4740_CLK_IPU] = {
+		"ipu", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR, 13 },
+	},
+
+	[JZ4740_CLK_ADC] = {
+		"adc", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 8 },
+	},
+
+	[JZ4740_CLK_I2C] = {
+		"i2c", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 3 },
+	},
+
+	[JZ4740_CLK_AIC] = {
+		"aic", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 5 },
+	},
+};
+
+static void __init jz4740_cgu_init(struct device_node *np)
+{
+	int retval;
+
+	cgu = ingenic_cgu_new(jz4740_cgu_clocks,
+			      ARRAY_SIZE(jz4740_cgu_clocks), np);
+	if (!cgu)
+		pr_err("%s: failed to initialise CGU\n", __func__);
+
+	retval = ingenic_cgu_register_clocks(cgu);
+	if (retval)
+		pr_err("%s: failed to register CGU Clocks\n", __func__);
+}
+CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
-- 
2.3.5

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

* [PATCH v3 26/37] MIPS,clk: migrate JZ4740 to common clock framework
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

Migrate the JZ4740 & the qi_lb60 board to use common clock framework
via the new Ingenic SoC CGU driver.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Co-authored-by: Paul Cercueil <paul@crapouillou.net>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Handle gating the "udc" clock.

Changes in v2:
  - None.
---
 arch/mips/Kconfig                      |   2 +-
 arch/mips/boot/dts/ingenic/jz4740.dtsi |  23 +
 arch/mips/boot/dts/ingenic/qi_lb60.dts |   4 +
 arch/mips/jz4740/Makefile              |   2 -
 arch/mips/jz4740/board-qi_lb60.c       |   5 -
 arch/mips/jz4740/clock-debugfs.c       | 108 -----
 arch/mips/jz4740/clock.c               | 801 +--------------------------------
 arch/mips/jz4740/clock.h               |  53 +--
 arch/mips/jz4740/time.c                |   2 +
 drivers/clk/ingenic/Makefile           |   1 +
 drivers/clk/ingenic/jz4740-cgu.c       | 220 +++++++++
 11 files changed, 253 insertions(+), 968 deletions(-)
 delete mode 100644 arch/mips/jz4740/clock-debugfs.c
 create mode 100644 drivers/clk/ingenic/jz4740-cgu.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 741e364..e3c859c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -297,7 +297,7 @@ config MACH_INGENIC
 	select IRQ_CPU
 	select ARCH_REQUIRE_GPIOLIB
 	select SYS_HAS_EARLY_PRINTK
-	select HAVE_CLK
+	select COMMON_CLK
 	select GENERIC_IRQ_CHIP
 	select BUILTIN_DTB
 	select USE_OF
diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index 3841024..ef679b4 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -1,3 +1,5 @@
+#include <dt-bindings/clock/jz4740-cgu.h>
+
 / {
 	#address-cells = <1>;
 	#size-cells = <1>;
@@ -20,4 +22,25 @@
 		interrupt-parent = <&cpuintc>;
 		interrupts = <2>;
 	};
+
+	ext: ext {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+	};
+
+	rtc: rtc {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	cgu: jz4740-cgu@10000000 {
+		compatible = "ingenic,jz4740-cgu";
+		reg = <0x10000000 0x100>;
+
+		clocks = <&ext>, <&rtc>;
+		clock-names = "ext", "rtc";
+
+		#clock-cells = <1>;
+	};
 };
diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts
index 0c0f639..106d13c 100644
--- a/arch/mips/boot/dts/ingenic/qi_lb60.dts
+++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -5,3 +5,7 @@
 / {
 	compatible = "qi,lb60", "ingenic,jz4740";
 };
+
+&ext {
+	clock-frequency = <12000000>;
+};
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 6cf5dd4..fdb12efc 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -7,8 +7,6 @@
 obj-y += prom.o time.o reset.o setup.o \
 	gpio.o clock.o platform.o timer.o serial.o
 
-obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
-
 # board specific support
 
 obj-$(CONFIG_JZ4740_QI_LB60)	+= board-qi_lb60.o
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 9dd051e..21b034c 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -497,11 +497,6 @@ static int __init qi_lb60_init_platform_devices(void)
 
 }
 
-struct jz4740_clock_board_data jz4740_clock_bdata = {
-	.ext_rate = 12000000,
-	.rtc_rate = 32768,
-};
-
 static __init int board_avt2(char *str)
 {
 	qi_lb60_mmc_pdata.card_detect_active_low = 1;
diff --git a/arch/mips/jz4740/clock-debugfs.c b/arch/mips/jz4740/clock-debugfs.c
deleted file mode 100644
index 325422d0..0000000
--- a/arch/mips/jz4740/clock-debugfs.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 SoC clock support debugfs entries
- *
- *  This program 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.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>
-
-#include <asm/mach-jz4740/clock.h>
-#include "clock.h"
-
-static struct dentry *jz4740_clock_debugfs;
-
-static int jz4740_clock_debugfs_show_enabled(void *data, uint64_t *value)
-{
-	struct clk *clk = data;
-	*value = clk_is_enabled(clk);
-
-	return 0;
-}
-
-static int jz4740_clock_debugfs_set_enabled(void *data, uint64_t value)
-{
-	struct clk *clk = data;
-
-	if (value)
-		return clk_enable(clk);
-	else
-		clk_disable(clk);
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_enabled,
-	jz4740_clock_debugfs_show_enabled,
-	jz4740_clock_debugfs_set_enabled,
-	"%llu\n");
-
-static int jz4740_clock_debugfs_show_rate(void *data, uint64_t *value)
-{
-	struct clk *clk = data;
-	*value = clk_get_rate(clk);
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(jz4740_clock_debugfs_ops_rate,
-	jz4740_clock_debugfs_show_rate,
-	NULL,
-	"%llu\n");
-
-void jz4740_clock_debugfs_add_clk(struct clk *clk)
-{
-	if (!jz4740_clock_debugfs)
-		return;
-
-	clk->debugfs_entry = debugfs_create_dir(clk->name, jz4740_clock_debugfs);
-	debugfs_create_file("rate", S_IWUGO | S_IRUGO, clk->debugfs_entry, clk,
-				&jz4740_clock_debugfs_ops_rate);
-	debugfs_create_file("enabled", S_IRUGO, clk->debugfs_entry, clk,
-				&jz4740_clock_debugfs_ops_enabled);
-
-	if (clk->parent) {
-		char parent_path[100];
-		snprintf(parent_path, 100, "../%s", clk->parent->name);
-		clk->debugfs_parent_entry = debugfs_create_symlink("parent",
-						clk->debugfs_entry,
-						parent_path);
-	}
-}
-
-/* TODO: Locking */
-void jz4740_clock_debugfs_update_parent(struct clk *clk)
-{
-	debugfs_remove(clk->debugfs_parent_entry);
-
-	if (clk->parent) {
-		char parent_path[100];
-		snprintf(parent_path, 100, "../%s", clk->parent->name);
-		clk->debugfs_parent_entry = debugfs_create_symlink("parent",
-						clk->debugfs_entry,
-						parent_path);
-	} else {
-		clk->debugfs_parent_entry = NULL;
-	}
-}
-
-void jz4740_clock_debugfs_init(void)
-{
-	jz4740_clock_debugfs = debugfs_create_dir("jz4740-clock", NULL);
-	if (IS_ERR(jz4740_clock_debugfs))
-		jz4740_clock_debugfs = NULL;
-}
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index c257073..dedee7c 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -27,820 +28,44 @@
 
 #include "clock.h"
 
-#define JZ_REG_CLOCK_CTRL	0x00
 #define JZ_REG_CLOCK_LOW_POWER	0x04
 #define JZ_REG_CLOCK_PLL	0x10
 #define JZ_REG_CLOCK_GATE	0x20
-#define JZ_REG_CLOCK_SLEEP_CTRL 0x24
-#define JZ_REG_CLOCK_I2S	0x60
-#define JZ_REG_CLOCK_LCD	0x64
-#define JZ_REG_CLOCK_MMC	0x68
-#define JZ_REG_CLOCK_UHC	0x6C
-#define JZ_REG_CLOCK_SPI	0x74
-
-#define JZ_CLOCK_CTRL_I2S_SRC_PLL	BIT(31)
-#define JZ_CLOCK_CTRL_KO_ENABLE		BIT(30)
-#define JZ_CLOCK_CTRL_UDC_SRC_PLL	BIT(29)
-#define JZ_CLOCK_CTRL_UDIV_MASK		0x1f800000
-#define JZ_CLOCK_CTRL_CHANGE_ENABLE	BIT(22)
-#define JZ_CLOCK_CTRL_PLL_HALF		BIT(21)
-#define JZ_CLOCK_CTRL_LDIV_MASK		0x001f0000
-#define JZ_CLOCK_CTRL_UDIV_OFFSET	23
-#define JZ_CLOCK_CTRL_LDIV_OFFSET	16
-#define JZ_CLOCK_CTRL_MDIV_OFFSET	12
-#define JZ_CLOCK_CTRL_PDIV_OFFSET	 8
-#define JZ_CLOCK_CTRL_HDIV_OFFSET	 4
-#define JZ_CLOCK_CTRL_CDIV_OFFSET	 0
 
 #define JZ_CLOCK_GATE_UART0	BIT(0)
 #define JZ_CLOCK_GATE_TCU	BIT(1)
-#define JZ_CLOCK_GATE_RTC	BIT(2)
-#define JZ_CLOCK_GATE_I2C	BIT(3)
-#define JZ_CLOCK_GATE_SPI	BIT(4)
-#define JZ_CLOCK_GATE_AIC	BIT(5)
-#define JZ_CLOCK_GATE_I2S	BIT(6)
-#define JZ_CLOCK_GATE_MMC	BIT(7)
-#define JZ_CLOCK_GATE_ADC	BIT(8)
-#define JZ_CLOCK_GATE_CIM	BIT(9)
-#define JZ_CLOCK_GATE_LCD	BIT(10)
 #define JZ_CLOCK_GATE_UDC	BIT(11)
 #define JZ_CLOCK_GATE_DMAC	BIT(12)
-#define JZ_CLOCK_GATE_IPU	BIT(13)
-#define JZ_CLOCK_GATE_UHC	BIT(14)
-#define JZ_CLOCK_GATE_UART1	BIT(15)
-
-#define JZ_CLOCK_I2S_DIV_MASK		0x01ff
-
-#define JZ_CLOCK_LCD_DIV_MASK		0x01ff
-
-#define JZ_CLOCK_MMC_DIV_MASK		0x001f
 
-#define JZ_CLOCK_UHC_DIV_MASK		0x000f
-
-#define JZ_CLOCK_SPI_SRC_PLL		BIT(31)
-#define JZ_CLOCK_SPI_DIV_MASK		0x000f
-
-#define JZ_CLOCK_PLL_M_MASK		0x01ff
-#define JZ_CLOCK_PLL_N_MASK		0x001f
-#define JZ_CLOCK_PLL_OD_MASK		0x0003
 #define JZ_CLOCK_PLL_STABLE		BIT(10)
-#define JZ_CLOCK_PLL_BYPASS		BIT(9)
 #define JZ_CLOCK_PLL_ENABLED		BIT(8)
-#define JZ_CLOCK_PLL_STABLIZE_MASK	0x000f
-#define JZ_CLOCK_PLL_M_OFFSET		23
-#define JZ_CLOCK_PLL_N_OFFSET		18
-#define JZ_CLOCK_PLL_OD_OFFSET		16
 
 #define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
 #define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
 
-#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
-#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
-
 static void __iomem *jz_clock_base;
-static spinlock_t jz_clock_lock;
-static LIST_HEAD(jz_clocks);
-
-struct main_clk {
-	struct clk clk;
-	uint32_t div_offset;
-};
-
-struct divided_clk {
-	struct clk clk;
-	uint32_t reg;
-	uint32_t mask;
-};
-
-struct static_clk {
-	struct clk clk;
-	unsigned long rate;
-};
 
 static uint32_t jz_clk_reg_read(int reg)
 {
 	return readl(jz_clock_base + reg);
 }
 
-static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask)
-{
-	uint32_t val2;
-
-	spin_lock(&jz_clock_lock);
-	val2 = readl(jz_clock_base + reg);
-	val2 &= ~mask;
-	val2 |= val;
-	writel(val2, jz_clock_base + reg);
-	spin_unlock(&jz_clock_lock);
-}
-
 static void jz_clk_reg_set_bits(int reg, uint32_t mask)
 {
 	uint32_t val;
 
-	spin_lock(&jz_clock_lock);
 	val = readl(jz_clock_base + reg);
 	val |= mask;
 	writel(val, jz_clock_base + reg);
-	spin_unlock(&jz_clock_lock);
 }
 
 static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
 {
 	uint32_t val;
 
-	spin_lock(&jz_clock_lock);
 	val = readl(jz_clock_base + reg);
 	val &= ~mask;
 	writel(val, jz_clock_base + reg);
-	spin_unlock(&jz_clock_lock);
-}
-
-static int jz_clk_enable_gating(struct clk *clk)
-{
-	if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
-		return -EINVAL;
-
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
-	return 0;
-}
-
-static int jz_clk_disable_gating(struct clk *clk)
-{
-	if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
-		return -EINVAL;
-
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
-	return 0;
-}
-
-static int jz_clk_is_enabled_gating(struct clk *clk)
-{
-	if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
-		return 1;
-
-	return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit);
-}
-
-static unsigned long jz_clk_static_get_rate(struct clk *clk)
-{
-	return ((struct static_clk *)clk)->rate;
-}
-
-static int jz_clk_ko_enable(struct clk *clk)
-{
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
-	return 0;
-}
-
-static int jz_clk_ko_disable(struct clk *clk)
-{
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
-	return 0;
-}
-
-static int jz_clk_ko_is_enabled(struct clk *clk)
-{
-	return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
-}
-
-static const int pllno[] = {1, 2, 2, 4};
-
-static unsigned long jz_clk_pll_get_rate(struct clk *clk)
-{
-	uint32_t val;
-	int m;
-	int n;
-	int od;
-
-	val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
-
-	if (val & JZ_CLOCK_PLL_BYPASS)
-		return clk_get_rate(clk->parent);
-
-	m = ((val >> 23) & 0x1ff) + 2;
-	n = ((val >> 18) & 0x1f) + 2;
-	od = (val >> 16) & 0x3;
-
-	return ((clk_get_rate(clk->parent) / n) * m) / pllno[od];
-}
-
-static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
-{
-	uint32_t reg;
-
-	reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-	if (reg & JZ_CLOCK_CTRL_PLL_HALF)
-		return jz_clk_pll_get_rate(clk->parent);
-	return jz_clk_pll_get_rate(clk->parent) >> 1;
-}
-
-static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
-
-static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
-	int div;
-
-	div = parent_rate / rate;
-	if (div > 32)
-		return parent_rate / 32;
-	else if (div < 1)
-		return parent_rate;
-
-	div &= (0x3 << (ffs(div) - 1));
-
-	return parent_rate / div;
-}
-
-static unsigned long jz_clk_main_get_rate(struct clk *clk)
-{
-	struct main_clk *mclk = (struct main_clk *)clk;
-	uint32_t div;
-
-	div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-
-	div >>= mclk->div_offset;
-	div &= 0xf;
-
-	if (div >= ARRAY_SIZE(jz_clk_main_divs))
-		div = ARRAY_SIZE(jz_clk_main_divs) - 1;
-
-	return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div];
-}
-
-static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
-{
-	struct main_clk *mclk = (struct main_clk *)clk;
-	int i;
-	int div;
-	unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
-
-	rate = jz_clk_main_round_rate(clk, rate);
-
-	div = parent_rate / rate;
-
-	i = (ffs(div) - 1) << 1;
-	if (i > 0 && !(div & BIT(i-1)))
-		i -= 1;
-
-	jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset,
-				0xf << mclk->div_offset);
-
-	return 0;
-}
-
-static struct clk_ops jz_clk_static_ops = {
-	.get_rate = jz_clk_static_get_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct static_clk jz_clk_ext = {
-	.clk = {
-		.name = "ext",
-		.gate_bit = JZ4740_CLK_NOT_GATED,
-		.ops = &jz_clk_static_ops,
-	},
-};
-
-static struct clk_ops jz_clk_pll_ops = {
-	.get_rate = jz_clk_pll_get_rate,
-};
-
-static struct clk jz_clk_pll = {
-	.name = "pll",
-	.parent = &jz_clk_ext.clk,
-	.ops = &jz_clk_pll_ops,
-};
-
-static struct clk_ops jz_clk_pll_half_ops = {
-	.get_rate = jz_clk_pll_half_get_rate,
-};
-
-static struct clk jz_clk_pll_half = {
-	.name = "pll half",
-	.parent = &jz_clk_pll,
-	.ops = &jz_clk_pll_half_ops,
-};
-
-static const struct clk_ops jz_clk_main_ops = {
-	.get_rate = jz_clk_main_get_rate,
-	.set_rate = jz_clk_main_set_rate,
-	.round_rate = jz_clk_main_round_rate,
-};
-
-static struct main_clk jz_clk_cpu = {
-	.clk = {
-		.name = "cclk",
-		.parent = &jz_clk_pll,
-		.ops = &jz_clk_main_ops,
-	},
-	.div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
-};
-
-static struct main_clk jz_clk_memory = {
-	.clk = {
-		.name = "mclk",
-		.parent = &jz_clk_pll,
-		.ops = &jz_clk_main_ops,
-	},
-	.div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
-};
-
-static struct main_clk jz_clk_high_speed_peripheral = {
-	.clk = {
-		.name = "hclk",
-		.parent = &jz_clk_pll,
-		.ops = &jz_clk_main_ops,
-	},
-	.div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
-};
-
-
-static struct main_clk jz_clk_low_speed_peripheral = {
-	.clk = {
-		.name = "pclk",
-		.parent = &jz_clk_pll,
-		.ops = &jz_clk_main_ops,
-	},
-	.div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
-};
-
-static const struct clk_ops jz_clk_ko_ops = {
-	.enable = jz_clk_ko_enable,
-	.disable = jz_clk_ko_disable,
-	.is_enabled = jz_clk_ko_is_enabled,
-};
-
-static struct clk jz_clk_ko = {
-	.name = "cko",
-	.parent = &jz_clk_memory.clk,
-	.ops = &jz_clk_ko_ops,
-};
-
-static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
-{
-	if (parent == &jz_clk_pll)
-		jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
-	else if (parent == &jz_clk_ext.clk)
-		jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	return 0;
-}
-
-static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
-{
-	if (parent == &jz_clk_pll_half)
-		jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
-	else if (parent == &jz_clk_ext.clk)
-		jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	return 0;
-}
-
-static int jz_clk_udc_enable(struct clk *clk)
-{
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL,
-			JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
-
-	return 0;
-}
-
-static int jz_clk_udc_disable(struct clk *clk)
-{
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL,
-			JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
-
-	return 0;
-}
-
-static int jz_clk_udc_is_enabled(struct clk *clk)
-{
-	return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) &
-			JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
-}
-
-static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
-{
-	if (parent == &jz_clk_pll_half)
-		jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
-	else if (parent == &jz_clk_ext.clk)
-		jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	return 0;
-}
-
-static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate)
-{
-	int div;
-
-	if (clk->parent == &jz_clk_ext.clk)
-		return -EINVAL;
-
-	div = clk_get_rate(clk->parent) / rate - 1;
-
-	if (div < 0)
-		div = 0;
-	else if (div > 63)
-		div = 63;
-
-	jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET,
-				JZ_CLOCK_CTRL_UDIV_MASK);
-	return 0;
-}
-
-static unsigned long jz_clk_udc_get_rate(struct clk *clk)
-{
-	int div;
-
-	if (clk->parent == &jz_clk_ext.clk)
-		return clk_get_rate(clk->parent);
-
-	div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK);
-	div >>= JZ_CLOCK_CTRL_UDIV_OFFSET;
-	div += 1;
-
-	return clk_get_rate(clk->parent) / div;
-}
-
-static unsigned long jz_clk_divided_get_rate(struct clk *clk)
-{
-	struct divided_clk *dclk = (struct divided_clk *)clk;
-	int div;
-
-	if (clk->parent == &jz_clk_ext.clk)
-		return clk_get_rate(clk->parent);
-
-	div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1;
-
-	return clk_get_rate(clk->parent) / div;
-}
-
-static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate)
-{
-	struct divided_clk *dclk = (struct divided_clk *)clk;
-	int div;
-
-	if (clk->parent == &jz_clk_ext.clk)
-		return -EINVAL;
-
-	div = clk_get_rate(clk->parent) / rate - 1;
-
-	if (div < 0)
-		div = 0;
-	else if (div > dclk->mask)
-		div = dclk->mask;
-
-	jz_clk_reg_write_mask(dclk->reg, div, dclk->mask);
-
-	return 0;
-}
-
-static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate)
-{
-	int div;
-	unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent);
-
-	if (rate > 150000000)
-		return 150000000;
-
-	div = parent_rate / rate;
-	if (div < 1)
-		div = 1;
-	else if (div > 32)
-		div = 32;
-
-	return parent_rate / div;
-}
-
-static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate)
-{
-	int div;
-
-	if (rate > 150000000)
-		return -EINVAL;
-
-	div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1;
-	if (div < 0)
-		div = 0;
-	else if (div > 31)
-		div = 31;
-
-	jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET,
-				JZ_CLOCK_CTRL_LDIV_MASK);
-
-	return 0;
-}
-
-static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
-{
-	int div;
-
-	div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK;
-	div >>= JZ_CLOCK_CTRL_LDIV_OFFSET;
-
-	return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
-}
-
-static const struct clk_ops jz_clk_ops_ld = {
-	.set_rate = jz_clk_ldclk_set_rate,
-	.get_rate = jz_clk_ldclk_get_rate,
-	.round_rate = jz_clk_ldclk_round_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct clk jz_clk_ld = {
-	.name = "lcd",
-	.gate_bit = JZ_CLOCK_GATE_LCD,
-	.parent = &jz_clk_pll_half,
-	.ops = &jz_clk_ops_ld,
-};
-
-static const struct clk_ops jz_clk_i2s_ops = {
-	.set_rate = jz_clk_divided_set_rate,
-	.get_rate = jz_clk_divided_get_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-	.set_parent = jz_clk_i2s_set_parent,
-};
-
-static const struct clk_ops jz_clk_spi_ops = {
-	.set_rate = jz_clk_divided_set_rate,
-	.get_rate = jz_clk_divided_get_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-	.set_parent = jz_clk_spi_set_parent,
-};
-
-static const struct clk_ops jz_clk_divided_ops = {
-	.set_rate = jz_clk_divided_set_rate,
-	.get_rate = jz_clk_divided_get_rate,
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct divided_clk jz4740_clock_divided_clks[] = {
-	[0] = {
-		.clk = {
-			.name = "i2s",
-			.parent = &jz_clk_ext.clk,
-			.gate_bit = JZ_CLOCK_GATE_I2S,
-			.ops = &jz_clk_i2s_ops,
-		},
-		.reg = JZ_REG_CLOCK_I2S,
-		.mask = JZ_CLOCK_I2S_DIV_MASK,
-	},
-	[1] = {
-		.clk = {
-			.name = "spi",
-			.parent = &jz_clk_ext.clk,
-			.gate_bit = JZ_CLOCK_GATE_SPI,
-			.ops = &jz_clk_spi_ops,
-		},
-		.reg = JZ_REG_CLOCK_SPI,
-		.mask = JZ_CLOCK_SPI_DIV_MASK,
-	},
-	[2] = {
-		.clk = {
-			.name = "lcd_pclk",
-			.parent = &jz_clk_pll_half,
-			.gate_bit = JZ4740_CLK_NOT_GATED,
-			.ops = &jz_clk_divided_ops,
-		},
-		.reg = JZ_REG_CLOCK_LCD,
-		.mask = JZ_CLOCK_LCD_DIV_MASK,
-	},
-	[3] = {
-		.clk = {
-			.name = "mmc",
-			.parent = &jz_clk_pll_half,
-			.gate_bit = JZ_CLOCK_GATE_MMC,
-			.ops = &jz_clk_divided_ops,
-		},
-		.reg = JZ_REG_CLOCK_MMC,
-		.mask = JZ_CLOCK_MMC_DIV_MASK,
-	},
-	[4] = {
-		.clk = {
-			.name = "uhc",
-			.parent = &jz_clk_pll_half,
-			.gate_bit = JZ_CLOCK_GATE_UHC,
-			.ops = &jz_clk_divided_ops,
-		},
-		.reg = JZ_REG_CLOCK_UHC,
-		.mask = JZ_CLOCK_UHC_DIV_MASK,
-	},
-};
-
-static const struct clk_ops jz_clk_udc_ops = {
-	.set_parent = jz_clk_udc_set_parent,
-	.set_rate = jz_clk_udc_set_rate,
-	.get_rate = jz_clk_udc_get_rate,
-	.enable = jz_clk_udc_enable,
-	.disable = jz_clk_udc_disable,
-	.is_enabled = jz_clk_udc_is_enabled,
-};
-
-static const struct clk_ops jz_clk_simple_ops = {
-	.enable = jz_clk_enable_gating,
-	.disable = jz_clk_disable_gating,
-	.is_enabled = jz_clk_is_enabled_gating,
-};
-
-static struct clk jz4740_clock_simple_clks[] = {
-	[0] = {
-		.name = "udc",
-		.parent = &jz_clk_ext.clk,
-		.ops = &jz_clk_udc_ops,
-	},
-	[1] = {
-		.name = "uart0",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_UART0,
-		.ops = &jz_clk_simple_ops,
-	},
-	[2] = {
-		.name = "uart1",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_UART1,
-		.ops = &jz_clk_simple_ops,
-	},
-	[3] = {
-		.name = "dma",
-		.parent = &jz_clk_high_speed_peripheral.clk,
-		.gate_bit = JZ_CLOCK_GATE_DMAC,
-		.ops = &jz_clk_simple_ops,
-	},
-	[4] = {
-		.name = "ipu",
-		.parent = &jz_clk_high_speed_peripheral.clk,
-		.gate_bit = JZ_CLOCK_GATE_IPU,
-		.ops = &jz_clk_simple_ops,
-	},
-	[5] = {
-		.name = "adc",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_ADC,
-		.ops = &jz_clk_simple_ops,
-	},
-	[6] = {
-		.name = "i2c",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_I2C,
-		.ops = &jz_clk_simple_ops,
-	},
-	[7] = {
-		.name = "aic",
-		.parent = &jz_clk_ext.clk,
-		.gate_bit = JZ_CLOCK_GATE_AIC,
-		.ops = &jz_clk_simple_ops,
-	},
-};
-
-static struct static_clk jz_clk_rtc = {
-	.clk = {
-		.name = "rtc",
-		.gate_bit = JZ_CLOCK_GATE_RTC,
-		.ops = &jz_clk_static_ops,
-	},
-	.rate = 32768,
-};
-
-int clk_enable(struct clk *clk)
-{
-	if (!clk->ops->enable)
-		return -EINVAL;
-
-	return clk->ops->enable(clk);
-}
-EXPORT_SYMBOL_GPL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-	if (clk->ops->disable)
-		clk->ops->disable(clk);
-}
-EXPORT_SYMBOL_GPL(clk_disable);
-
-int clk_is_enabled(struct clk *clk)
-{
-	if (clk->ops->is_enabled)
-		return clk->ops->is_enabled(clk);
-
-	return 1;
-}
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (clk->ops->get_rate)
-		return clk->ops->get_rate(clk);
-	if (clk->parent)
-		return clk_get_rate(clk->parent);
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(clk_get_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	if (!clk->ops->set_rate)
-		return -EINVAL;
-	return clk->ops->set_rate(clk, rate);
-}
-EXPORT_SYMBOL_GPL(clk_set_rate);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	if (clk->ops->round_rate)
-		return clk->ops->round_rate(clk, rate);
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(clk_round_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	int ret;
-	int enabled;
-
-	if (!clk->ops->set_parent)
-		return -EINVAL;
-
-	enabled = clk_is_enabled(clk);
-	if (enabled)
-		clk_disable(clk);
-	ret = clk->ops->set_parent(clk, parent);
-	if (enabled)
-		clk_enable(clk);
-
-	jz4740_clock_debugfs_update_parent(clk);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(clk_set_parent);
-
-struct clk *clk_get(struct device *dev, const char *name)
-{
-	struct clk *clk;
-
-	list_for_each_entry(clk, &jz_clocks, list) {
-		if (strcmp(clk->name, name) == 0)
-			return clk;
-	}
-	return ERR_PTR(-ENXIO);
-}
-EXPORT_SYMBOL_GPL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL_GPL(clk_put);
-
-static inline void clk_add(struct clk *clk)
-{
-	list_add_tail(&clk->list, &jz_clocks);
-
-	jz4740_clock_debugfs_add_clk(clk);
-}
-
-static void clk_register_clks(void)
-{
-	size_t i;
-
-	clk_add(&jz_clk_ext.clk);
-	clk_add(&jz_clk_pll);
-	clk_add(&jz_clk_pll_half);
-	clk_add(&jz_clk_cpu.clk);
-	clk_add(&jz_clk_high_speed_peripheral.clk);
-	clk_add(&jz_clk_low_speed_peripheral.clk);
-	clk_add(&jz_clk_ko);
-	clk_add(&jz_clk_ld);
-	clk_add(&jz_clk_rtc.clk);
-
-	for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i)
-		clk_add(&jz4740_clock_divided_clks[i].clk);
-
-	for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i)
-		clk_add(&jz4740_clock_simple_clks[i]);
 }
 
 void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
@@ -891,33 +116,9 @@ void jz4740_clock_resume(void)
 
 int jz4740_clock_init(void)
 {
-	uint32_t val;
-
 	jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100);
 	if (!jz_clock_base)
 		return -EBUSY;
 
-	spin_lock_init(&jz_clock_lock);
-
-	jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
-	jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate;
-
-	val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
-
-	if (val & JZ_CLOCK_SPI_SRC_PLL)
-		jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half;
-
-	val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-
-	if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
-		jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half;
-
-	if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
-		jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half;
-
-	jz4740_clock_debugfs_init();
-
-	clk_register_clks();
-
 	return 0;
 }
diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h
index 5d07499..86a3e01 100644
--- a/arch/mips/jz4740/clock.h
+++ b/arch/mips/jz4740/clock.h
@@ -16,61 +16,10 @@
 #ifndef __MIPS_JZ4740_CLOCK_H__
 #define __MIPS_JZ4740_CLOCK_H__
 
+#include <linux/clk.h>
 #include <linux/list.h>
 
-struct jz4740_clock_board_data {
-	unsigned long ext_rate;
-	unsigned long rtc_rate;
-};
-
-extern struct jz4740_clock_board_data jz4740_clock_bdata;
-
 void jz4740_clock_suspend(void);
 void jz4740_clock_resume(void);
 
-struct clk;
-
-struct clk_ops {
-	unsigned long (*get_rate)(struct clk *clk);
-	unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
-	int (*set_rate)(struct clk *clk, unsigned long rate);
-	int (*enable)(struct clk *clk);
-	int (*disable)(struct clk *clk);
-	int (*is_enabled)(struct clk *clk);
-
-	int (*set_parent)(struct clk *clk, struct clk *parent);
-
-};
-
-struct clk {
-	const char *name;
-	struct clk *parent;
-
-	uint32_t gate_bit;
-
-	const struct clk_ops *ops;
-
-	struct list_head list;
-
-#ifdef CONFIG_DEBUG_FS
-	struct dentry *debugfs_entry;
-	struct dentry *debugfs_parent_entry;
-#endif
-
-};
-
-#define JZ4740_CLK_NOT_GATED ((uint32_t)-1)
-
-int clk_is_enabled(struct clk *clk);
-
-#ifdef CONFIG_DEBUG_FS
-void jz4740_clock_debugfs_init(void);
-void jz4740_clock_debugfs_add_clk(struct clk *clk);
-void jz4740_clock_debugfs_update_parent(struct clk *clk);
-#else
-static inline void jz4740_clock_debugfs_init(void) {};
-static inline void jz4740_clock_debugfs_add_clk(struct clk *clk) {};
-static inline void jz4740_clock_debugfs_update_parent(struct clk *clk) {};
-#endif
-
 #endif
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index f66f7f5..be9b0a3 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -14,6 +14,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
@@ -118,6 +119,7 @@ void __init plat_time_init(void)
 	uint16_t ctrl;
 	struct clk *ext_clk;
 
+	of_clk_init(NULL);
 	jz4740_clock_init();
 	jz4740_timer_init();
 
diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index 5ac2fd9..e6db7da 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -1 +1,2 @@
 obj-y				+= cgu.o
+obj-$(CONFIG_MACH_JZ4740)	+= jz4740-cgu.o
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
new file mode 100644
index 0000000..f3c95af
--- /dev/null
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -0,0 +1,220 @@
+/*
+ * Ingenic JZ4740 SoC CGU driver
+ *
+ * Copyright (c) 2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <dt-bindings/clock/jz4740-cgu.h>
+#include "cgu.h"
+
+/* CGU register offsets */
+#define CGU_REG_CPCCR		0x00
+#define CGU_REG_CPPCR		0x10
+#define CGU_REG_SCR		0x24
+#define CGU_REG_I2SCDR		0x60
+#define CGU_REG_LPCDR		0x64
+#define CGU_REG_MSCCDR		0x68
+#define CGU_REG_UHCCDR		0x6c
+#define CGU_REG_SSICDR		0x74
+
+/* bits within a PLL control register */
+#define PLLCTL_M_SHIFT		23
+#define PLLCTL_M_MASK		(0x1ff << PLLCTL_M_SHIFT)
+#define PLLCTL_N_SHIFT		18
+#define PLLCTL_N_MASK		(0x1f << PLLCTL_N_SHIFT)
+#define PLLCTL_OD_SHIFT		16
+#define PLLCTL_OD_MASK		(0x3 << PLLCTL_OD_SHIFT)
+#define PLLCTL_STABLE		(1 << 10)
+#define PLLCTL_BYPASS		(1 << 9)
+#define PLLCTL_ENABLE		(1 << 8)
+
+static struct ingenic_cgu *cgu;
+
+static const s8 pll_od_encoding[4] = {
+	0x0, 0x1, -1, 0x3,
+};
+
+static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
+
+	/* External clocks */
+
+	[JZ4740_CLK_EXT] = { "ext", CGU_CLK_EXT },
+	[JZ4740_CLK_RTC] = { "rtc", CGU_CLK_EXT },
+
+	[JZ4740_CLK_PLL] = {
+		"pll", CGU_CLK_PLL,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.pll = {
+			.reg = CGU_REG_CPPCR,
+			.m_shift = 23,
+			.m_bits = 9,
+			.m_offset = 2,
+			.n_shift = 18,
+			.n_bits = 5,
+			.n_offset = 2,
+			.od_shift = 16,
+			.od_bits = 2,
+			.od_max = 4,
+			.od_encoding = pll_od_encoding,
+			.stable_bit = 10,
+			.bypass_bit = 9,
+			.enable_bit = 8,
+		},
+	},
+
+	/* Muxes & dividers */
+
+	[JZ4740_CLK_PLL_HALF] = {
+		"pll half", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 21, 1, -1, -1, -1 },
+	},
+
+	[JZ4740_CLK_CCLK] = {
+		"cclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 0, 4, 22, -1, -1 },
+	},
+
+	[JZ4740_CLK_HCLK] = {
+		"hclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 4, 4, 22, -1, -1 },
+	},
+
+	[JZ4740_CLK_PCLK] = {
+		"pclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 8, 4, 22, -1, -1 },
+	},
+
+	[JZ4740_CLK_MCLK] = {
+		"mclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL, -1 },
+		.div = { CGU_REG_CPCCR, 12, 4, 22, -1, -1 },
+	},
+
+	[JZ4740_CLK_LCD] = {
+		"lcd", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PLL_HALF, -1 },
+		.div = { CGU_REG_CPCCR, 16, 5, 22, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 10 },
+	},
+
+	[JZ4740_CLK_LCD_PCLK] = {
+		"lcd_pclk", CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_PLL_HALF, -1 },
+		.div = { CGU_REG_LPCDR, 0, 11, -1, -1, -1 },
+	},
+
+	[JZ4740_CLK_I2S] = {
+		"i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1 },
+		.mux = { CGU_REG_CPCCR, 31, 1 },
+		.div = { CGU_REG_I2SCDR, 0, 8, -1, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 6 },
+	},
+
+	[JZ4740_CLK_SPI] = {
+		"spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1 },
+		.mux = { CGU_REG_SSICDR, 31, 1 },
+		.div = { CGU_REG_SSICDR, 0, 4, -1, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 4 },
+	},
+
+	[JZ4740_CLK_MMC] = {
+		"mmc", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PLL_HALF, -1 },
+		.div = { CGU_REG_MSCCDR, 0, 5, -1, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 7 },
+	},
+
+	[JZ4740_CLK_UHC] = {
+		"uhc", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PLL_HALF, -1 },
+		.div = { CGU_REG_UHCCDR, 0, 4, -1, -1, -1 },
+		.gate = { CGU_REG_CLKGR, 14 },
+	},
+
+	[JZ4740_CLK_UDC] = {
+		"udc", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1 },
+		.mux = { CGU_REG_CPCCR, 29, 1 },
+		.div = { CGU_REG_CPCCR, 23, 6, -1, -1, -1 },
+		.gate = { CGU_REG_SCR, 6 },
+	},
+
+	/* Gate-only clocks */
+
+	[JZ4740_CLK_UART0] = {
+		"uart0", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 0 },
+	},
+
+	[JZ4740_CLK_UART1] = {
+		"uart1", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 15 },
+	},
+
+	[JZ4740_CLK_DMA] = {
+		"dma", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR, 12 },
+	},
+
+	[JZ4740_CLK_IPU] = {
+		"ipu", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR, 13 },
+	},
+
+	[JZ4740_CLK_ADC] = {
+		"adc", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 8 },
+	},
+
+	[JZ4740_CLK_I2C] = {
+		"i2c", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 3 },
+	},
+
+	[JZ4740_CLK_AIC] = {
+		"aic", CGU_CLK_GATE,
+		.parents = { JZ4740_CLK_EXT, -1 },
+		.gate = { CGU_REG_CLKGR, 5 },
+	},
+};
+
+static void __init jz4740_cgu_init(struct device_node *np)
+{
+	int retval;
+
+	cgu = ingenic_cgu_new(jz4740_cgu_clocks,
+			      ARRAY_SIZE(jz4740_cgu_clocks), np);
+	if (!cgu)
+		pr_err("%s: failed to initialise CGU\n", __func__);
+
+	retval = ingenic_cgu_register_clocks(cgu);
+	if (retval)
+		pr_err("%s: failed to register CGU Clocks\n", __func__);
+}
+CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
-- 
2.3.5

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

* [PATCH v3 27/37] MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

The jz4740-cgu driver already has access to the CGU, so it makes sense
to move the few remaining accesses to the CGU from arch/mips/jz4740
there too. Move jz4740_clock_set_wait_mode for such consistency.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/clock.c         | 16 ----------------
 drivers/clk/ingenic/jz4740-cgu.c | 22 ++++++++++++++++++++++
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index dedee7c..90b44d7 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -28,7 +28,6 @@
 
 #include "clock.h"
 
-#define JZ_REG_CLOCK_LOW_POWER	0x04
 #define JZ_REG_CLOCK_PLL	0x10
 #define JZ_REG_CLOCK_GATE	0x20
 
@@ -40,9 +39,6 @@
 #define JZ_CLOCK_PLL_STABLE		BIT(10)
 #define JZ_CLOCK_PLL_ENABLED		BIT(8)
 
-#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
-#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
-
 static void __iomem *jz_clock_base;
 
 static uint32_t jz_clk_reg_read(int reg)
@@ -68,18 +64,6 @@ static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
 	writel(val, jz_clock_base + reg);
 }
 
-void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
-{
-	switch (mode) {
-	case JZ4740_WAIT_MODE_IDLE:
-		jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
-		break;
-	case JZ4740_WAIT_MODE_SLEEP:
-		jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
-		break;
-	}
-}
-
 void jz4740_clock_udc_disable_auto_suspend(void)
 {
 	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
index f3c95af..62230d2 100644
--- a/drivers/clk/ingenic/jz4740-cgu.c
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -19,10 +19,12 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <dt-bindings/clock/jz4740-cgu.h>
+#include <asm/mach-jz4740/clock.h>
 #include "cgu.h"
 
 /* CGU register offsets */
 #define CGU_REG_CPCCR		0x00
+#define CGU_REG_LCR		0x04
 #define CGU_REG_CPPCR		0x10
 #define CGU_REG_SCR		0x24
 #define CGU_REG_I2SCDR		0x60
@@ -42,6 +44,9 @@
 #define PLLCTL_BYPASS		(1 << 9)
 #define PLLCTL_ENABLE		(1 << 8)
 
+/* bits within the LCR register */
+#define LCR_SLEEP		(1 << 0)
+
 static struct ingenic_cgu *cgu;
 
 static const s8 pll_od_encoding[4] = {
@@ -218,3 +223,20 @@ static void __init jz4740_cgu_init(struct device_node *np)
 		pr_err("%s: failed to register CGU Clocks\n", __func__);
 }
 CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
+
+void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
+{
+	uint32_t lcr = readl(cgu->base + CGU_REG_LCR);
+
+	switch (mode) {
+	case JZ4740_WAIT_MODE_IDLE:
+		lcr &= ~LCR_SLEEP;
+		break;
+
+	case JZ4740_WAIT_MODE_SLEEP:
+		lcr |= LCR_SLEEP;
+		break;
+	}
+
+	writel(lcr, cgu->base + CGU_REG_LCR);
+}
-- 
2.3.5

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

* [PATCH v3 27/37] MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

The jz4740-cgu driver already has access to the CGU, so it makes sense
to move the few remaining accesses to the CGU from arch/mips/jz4740
there too. Move jz4740_clock_set_wait_mode for such consistency.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/clock.c         | 16 ----------------
 drivers/clk/ingenic/jz4740-cgu.c | 22 ++++++++++++++++++++++
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index dedee7c..90b44d7 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -28,7 +28,6 @@
 
 #include "clock.h"
 
-#define JZ_REG_CLOCK_LOW_POWER	0x04
 #define JZ_REG_CLOCK_PLL	0x10
 #define JZ_REG_CLOCK_GATE	0x20
 
@@ -40,9 +39,6 @@
 #define JZ_CLOCK_PLL_STABLE		BIT(10)
 #define JZ_CLOCK_PLL_ENABLED		BIT(8)
 
-#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
-#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
-
 static void __iomem *jz_clock_base;
 
 static uint32_t jz_clk_reg_read(int reg)
@@ -68,18 +64,6 @@ static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
 	writel(val, jz_clock_base + reg);
 }
 
-void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
-{
-	switch (mode) {
-	case JZ4740_WAIT_MODE_IDLE:
-		jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
-		break;
-	case JZ4740_WAIT_MODE_SLEEP:
-		jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
-		break;
-	}
-}
-
 void jz4740_clock_udc_disable_auto_suspend(void)
 {
 	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
index f3c95af..62230d2 100644
--- a/drivers/clk/ingenic/jz4740-cgu.c
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -19,10 +19,12 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 #include <dt-bindings/clock/jz4740-cgu.h>
+#include <asm/mach-jz4740/clock.h>
 #include "cgu.h"
 
 /* CGU register offsets */
 #define CGU_REG_CPCCR		0x00
+#define CGU_REG_LCR		0x04
 #define CGU_REG_CPPCR		0x10
 #define CGU_REG_SCR		0x24
 #define CGU_REG_I2SCDR		0x60
@@ -42,6 +44,9 @@
 #define PLLCTL_BYPASS		(1 << 9)
 #define PLLCTL_ENABLE		(1 << 8)
 
+/* bits within the LCR register */
+#define LCR_SLEEP		(1 << 0)
+
 static struct ingenic_cgu *cgu;
 
 static const s8 pll_od_encoding[4] = {
@@ -218,3 +223,20 @@ static void __init jz4740_cgu_init(struct device_node *np)
 		pr_err("%s: failed to register CGU Clocks\n", __func__);
 }
 CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
+
+void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
+{
+	uint32_t lcr = readl(cgu->base + CGU_REG_LCR);
+
+	switch (mode) {
+	case JZ4740_WAIT_MODE_IDLE:
+		lcr &= ~LCR_SLEEP;
+		break;
+
+	case JZ4740_WAIT_MODE_SLEEP:
+		lcr |= LCR_SLEEP;
+		break;
+	}
+
+	writel(lcr, cgu->base + CGU_REG_LCR);
+}
-- 
2.3.5

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

* [PATCH v3 28/37] MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

The jz4740-cgu driver already has access to the CGU, so it makes sense
to move the few remaining accesses to the CGU from arch/mips/jz4740
there too. Move the jz4740_clock_udc_{dis,en}able_auto_suspend functions
there for such consistency.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/clock.c         | 13 -------------
 drivers/clk/ingenic/jz4740-cgu.c | 22 ++++++++++++++++++++++
 2 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index 90b44d7..2a10829 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -33,7 +33,6 @@
 
 #define JZ_CLOCK_GATE_UART0	BIT(0)
 #define JZ_CLOCK_GATE_TCU	BIT(1)
-#define JZ_CLOCK_GATE_UDC	BIT(11)
 #define JZ_CLOCK_GATE_DMAC	BIT(12)
 
 #define JZ_CLOCK_PLL_STABLE		BIT(10)
@@ -64,18 +63,6 @@ static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
 	writel(val, jz_clock_base + reg);
 }
 
-void jz4740_clock_udc_disable_auto_suspend(void)
-{
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
-}
-EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
-
-void jz4740_clock_udc_enable_auto_suspend(void)
-{
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
-}
-EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
-
 void jz4740_clock_suspend(void)
 {
 	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
index 62230d2..fee5c89 100644
--- a/drivers/clk/ingenic/jz4740-cgu.c
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -26,6 +26,7 @@
 #define CGU_REG_CPCCR		0x00
 #define CGU_REG_LCR		0x04
 #define CGU_REG_CPPCR		0x10
+#define CGU_REG_CLKGR		0x20
 #define CGU_REG_SCR		0x24
 #define CGU_REG_I2SCDR		0x60
 #define CGU_REG_LPCDR		0x64
@@ -47,6 +48,9 @@
 /* bits within the LCR register */
 #define LCR_SLEEP		(1 << 0)
 
+/* bits within the CLKGR register */
+#define CLKGR_UDC		(1 << 11)
+
 static struct ingenic_cgu *cgu;
 
 static const s8 pll_od_encoding[4] = {
@@ -240,3 +244,21 @@ void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
 
 	writel(lcr, cgu->base + CGU_REG_LCR);
 }
+
+void jz4740_clock_udc_disable_auto_suspend(void)
+{
+	uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR);
+
+	clkgr &= ~CLKGR_UDC;
+	writel(clkgr, cgu->base + CGU_REG_CLKGR);
+}
+EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
+
+void jz4740_clock_udc_enable_auto_suspend(void)
+{
+	uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR);
+
+	clkgr |= CLKGR_UDC;
+	writel(clkgr, cgu->base + CGU_REG_CLKGR);
+}
+EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
-- 
2.3.5

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

* [PATCH v3 28/37] MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

The jz4740-cgu driver already has access to the CGU, so it makes sense
to move the few remaining accesses to the CGU from arch/mips/jz4740
there too. Move the jz4740_clock_udc_{dis,en}able_auto_suspend functions
there for such consistency.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/jz4740/clock.c         | 13 -------------
 drivers/clk/ingenic/jz4740-cgu.c | 22 ++++++++++++++++++++++
 2 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
index 90b44d7..2a10829 100644
--- a/arch/mips/jz4740/clock.c
+++ b/arch/mips/jz4740/clock.c
@@ -33,7 +33,6 @@
 
 #define JZ_CLOCK_GATE_UART0	BIT(0)
 #define JZ_CLOCK_GATE_TCU	BIT(1)
-#define JZ_CLOCK_GATE_UDC	BIT(11)
 #define JZ_CLOCK_GATE_DMAC	BIT(12)
 
 #define JZ_CLOCK_PLL_STABLE		BIT(10)
@@ -64,18 +63,6 @@ static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
 	writel(val, jz_clock_base + reg);
 }
 
-void jz4740_clock_udc_disable_auto_suspend(void)
-{
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
-}
-EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
-
-void jz4740_clock_udc_enable_auto_suspend(void)
-{
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
-}
-EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
-
 void jz4740_clock_suspend(void)
 {
 	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
index 62230d2..fee5c89 100644
--- a/drivers/clk/ingenic/jz4740-cgu.c
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -26,6 +26,7 @@
 #define CGU_REG_CPCCR		0x00
 #define CGU_REG_LCR		0x04
 #define CGU_REG_CPPCR		0x10
+#define CGU_REG_CLKGR		0x20
 #define CGU_REG_SCR		0x24
 #define CGU_REG_I2SCDR		0x60
 #define CGU_REG_LPCDR		0x64
@@ -47,6 +48,9 @@
 /* bits within the LCR register */
 #define LCR_SLEEP		(1 << 0)
 
+/* bits within the CLKGR register */
+#define CLKGR_UDC		(1 << 11)
+
 static struct ingenic_cgu *cgu;
 
 static const s8 pll_od_encoding[4] = {
@@ -240,3 +244,21 @@ void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
 
 	writel(lcr, cgu->base + CGU_REG_LCR);
 }
+
+void jz4740_clock_udc_disable_auto_suspend(void)
+{
+	uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR);
+
+	clkgr &= ~CLKGR_UDC;
+	writel(clkgr, cgu->base + CGU_REG_CLKGR);
+}
+EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
+
+void jz4740_clock_udc_enable_auto_suspend(void)
+{
+	uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR);
+
+	clkgr |= CLKGR_UDC;
+	writel(clkgr, cgu->base + CGU_REG_CLKGR);
+}
+EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
-- 
2.3.5

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

* [PATCH v3 29/37] MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

The jz4740-cgu driver already has access to the CGU, so it makes sense
to move the few remaining accesses to the CGU from arch/mips/jz4740
there too. Move the jz4740_clock_{suspend,resume} functions there for
such consistency. The arch/mips/jz4740/clock.c file now contains nothing
more of use & so is removed.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/clock.h |  2 -
 arch/mips/jz4740/Makefile                 |  2 +-
 arch/mips/jz4740/clock.c                  | 95 -------------------------------
 arch/mips/jz4740/time.c                   |  1 -
 drivers/clk/ingenic/jz4740-cgu.c          | 37 ++++++++++++
 5 files changed, 38 insertions(+), 99 deletions(-)
 delete mode 100644 arch/mips/jz4740/clock.c

diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h
index 01d8468..16659cd 100644
--- a/arch/mips/include/asm/mach-jz4740/clock.h
+++ b/arch/mips/include/asm/mach-jz4740/clock.h
@@ -20,8 +20,6 @@ enum jz4740_wait_mode {
 	JZ4740_WAIT_MODE_SLEEP,
 };
 
-int jz4740_clock_init(void);
-
 void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode);
 
 void jz4740_clock_udc_enable_auto_suspend(void);
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index fdb12efc..7636432 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -5,7 +5,7 @@
 # Object file lists.
 
 obj-y += prom.o time.o reset.o setup.o \
-	gpio.o clock.o platform.o timer.o serial.o
+	gpio.o platform.o timer.o serial.o
 
 # board specific support
 
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
deleted file mode 100644
index 2a10829..0000000
--- a/arch/mips/jz4740/clock.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 SoC clock support
- *
- *  This program 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.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/err.h>
-
-#include <asm/mach-jz4740/clock.h>
-#include <asm/mach-jz4740/base.h>
-
-#include "clock.h"
-
-#define JZ_REG_CLOCK_PLL	0x10
-#define JZ_REG_CLOCK_GATE	0x20
-
-#define JZ_CLOCK_GATE_UART0	BIT(0)
-#define JZ_CLOCK_GATE_TCU	BIT(1)
-#define JZ_CLOCK_GATE_DMAC	BIT(12)
-
-#define JZ_CLOCK_PLL_STABLE		BIT(10)
-#define JZ_CLOCK_PLL_ENABLED		BIT(8)
-
-static void __iomem *jz_clock_base;
-
-static uint32_t jz_clk_reg_read(int reg)
-{
-	return readl(jz_clock_base + reg);
-}
-
-static void jz_clk_reg_set_bits(int reg, uint32_t mask)
-{
-	uint32_t val;
-
-	val = readl(jz_clock_base + reg);
-	val |= mask;
-	writel(val, jz_clock_base + reg);
-}
-
-static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
-{
-	uint32_t val;
-
-	val = readl(jz_clock_base + reg);
-	val &= ~mask;
-	writel(val, jz_clock_base + reg);
-}
-
-void jz4740_clock_suspend(void)
-{
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
-		JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
-
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
-}
-
-void jz4740_clock_resume(void)
-{
-	uint32_t pll;
-
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
-
-	do {
-		pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
-	} while (!(pll & JZ_CLOCK_PLL_STABLE));
-
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE,
-		JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
-}
-
-int jz4740_clock_init(void)
-{
-	jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100);
-	if (!jz_clock_base)
-		return -EBUSY;
-
-	return 0;
-}
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index be9b0a3..9172553 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -120,7 +120,6 @@ void __init plat_time_init(void)
 	struct clk *ext_clk;
 
 	of_clk_init(NULL);
-	jz4740_clock_init();
 	jz4740_timer_init();
 
 	ext_clk = clk_get(NULL, "ext");
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
index fee5c89..bb37657 100644
--- a/drivers/clk/ingenic/jz4740-cgu.c
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -262,3 +262,40 @@ void jz4740_clock_udc_enable_auto_suspend(void)
 	writel(clkgr, cgu->base + CGU_REG_CLKGR);
 }
 EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
+
+#define JZ_CLOCK_GATE_UART0	BIT(0)
+#define JZ_CLOCK_GATE_TCU	BIT(1)
+#define JZ_CLOCK_GATE_DMAC	BIT(12)
+
+void jz4740_clock_suspend(void)
+{
+	uint32_t clkgr, cppcr;
+
+	clkgr = readl(cgu->base + CGU_REG_CLKGR);
+	clkgr |= JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0;
+	writel(clkgr, cgu->base + CGU_REG_CLKGR);
+
+	cppcr = readl(cgu->base + CGU_REG_CPPCR);
+	cppcr &= ~BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit);
+	writel(cppcr, cgu->base + CGU_REG_CPPCR);
+}
+
+void jz4740_clock_resume(void)
+{
+	uint32_t clkgr, cppcr, stable;
+
+	cppcr = readl(cgu->base + CGU_REG_CPPCR);
+	cppcr |= BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit);
+	writel(cppcr, cgu->base + CGU_REG_CPPCR);
+
+	stable = BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.stable_bit);
+	do {
+		cppcr = readl(cgu->base + CGU_REG_CPPCR);
+	} while (!(cppcr & stable));
+
+	clkgr = readl(cgu->base + CGU_REG_CLKGR);
+	clkgr &= ~JZ_CLOCK_GATE_TCU;
+	clkgr &= ~JZ_CLOCK_GATE_DMAC;
+	clkgr &= ~JZ_CLOCK_GATE_UART0;
+	writel(clkgr, cgu->base + CGU_REG_CLKGR);
+}
-- 
2.3.5

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

* [PATCH v3 29/37] MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

The jz4740-cgu driver already has access to the CGU, so it makes sense
to move the few remaining accesses to the CGU from arch/mips/jz4740
there too. Move the jz4740_clock_{suspend,resume} functions there for
such consistency. The arch/mips/jz4740/clock.c file now contains nothing
more of use & so is removed.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/clock.h |  2 -
 arch/mips/jz4740/Makefile                 |  2 +-
 arch/mips/jz4740/clock.c                  | 95 -------------------------------
 arch/mips/jz4740/time.c                   |  1 -
 drivers/clk/ingenic/jz4740-cgu.c          | 37 ++++++++++++
 5 files changed, 38 insertions(+), 99 deletions(-)
 delete mode 100644 arch/mips/jz4740/clock.c

diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h
index 01d8468..16659cd 100644
--- a/arch/mips/include/asm/mach-jz4740/clock.h
+++ b/arch/mips/include/asm/mach-jz4740/clock.h
@@ -20,8 +20,6 @@ enum jz4740_wait_mode {
 	JZ4740_WAIT_MODE_SLEEP,
 };
 
-int jz4740_clock_init(void);
-
 void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode);
 
 void jz4740_clock_udc_enable_auto_suspend(void);
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index fdb12efc..7636432 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -5,7 +5,7 @@
 # Object file lists.
 
 obj-y += prom.o time.o reset.o setup.o \
-	gpio.o clock.o platform.o timer.o serial.o
+	gpio.o platform.o timer.o serial.o
 
 # board specific support
 
diff --git a/arch/mips/jz4740/clock.c b/arch/mips/jz4740/clock.c
deleted file mode 100644
index 2a10829..0000000
--- a/arch/mips/jz4740/clock.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 SoC clock support
- *
- *  This program 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.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/err.h>
-
-#include <asm/mach-jz4740/clock.h>
-#include <asm/mach-jz4740/base.h>
-
-#include "clock.h"
-
-#define JZ_REG_CLOCK_PLL	0x10
-#define JZ_REG_CLOCK_GATE	0x20
-
-#define JZ_CLOCK_GATE_UART0	BIT(0)
-#define JZ_CLOCK_GATE_TCU	BIT(1)
-#define JZ_CLOCK_GATE_DMAC	BIT(12)
-
-#define JZ_CLOCK_PLL_STABLE		BIT(10)
-#define JZ_CLOCK_PLL_ENABLED		BIT(8)
-
-static void __iomem *jz_clock_base;
-
-static uint32_t jz_clk_reg_read(int reg)
-{
-	return readl(jz_clock_base + reg);
-}
-
-static void jz_clk_reg_set_bits(int reg, uint32_t mask)
-{
-	uint32_t val;
-
-	val = readl(jz_clock_base + reg);
-	val |= mask;
-	writel(val, jz_clock_base + reg);
-}
-
-static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
-{
-	uint32_t val;
-
-	val = readl(jz_clock_base + reg);
-	val &= ~mask;
-	writel(val, jz_clock_base + reg);
-}
-
-void jz4740_clock_suspend(void)
-{
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
-		JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
-
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
-}
-
-void jz4740_clock_resume(void)
-{
-	uint32_t pll;
-
-	jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
-
-	do {
-		pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
-	} while (!(pll & JZ_CLOCK_PLL_STABLE));
-
-	jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE,
-		JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
-}
-
-int jz4740_clock_init(void)
-{
-	jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100);
-	if (!jz_clock_base)
-		return -EBUSY;
-
-	return 0;
-}
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index be9b0a3..9172553 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -120,7 +120,6 @@ void __init plat_time_init(void)
 	struct clk *ext_clk;
 
 	of_clk_init(NULL);
-	jz4740_clock_init();
 	jz4740_timer_init();
 
 	ext_clk = clk_get(NULL, "ext");
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
index fee5c89..bb37657 100644
--- a/drivers/clk/ingenic/jz4740-cgu.c
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -262,3 +262,40 @@ void jz4740_clock_udc_enable_auto_suspend(void)
 	writel(clkgr, cgu->base + CGU_REG_CLKGR);
 }
 EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
+
+#define JZ_CLOCK_GATE_UART0	BIT(0)
+#define JZ_CLOCK_GATE_TCU	BIT(1)
+#define JZ_CLOCK_GATE_DMAC	BIT(12)
+
+void jz4740_clock_suspend(void)
+{
+	uint32_t clkgr, cppcr;
+
+	clkgr = readl(cgu->base + CGU_REG_CLKGR);
+	clkgr |= JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0;
+	writel(clkgr, cgu->base + CGU_REG_CLKGR);
+
+	cppcr = readl(cgu->base + CGU_REG_CPPCR);
+	cppcr &= ~BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit);
+	writel(cppcr, cgu->base + CGU_REG_CPPCR);
+}
+
+void jz4740_clock_resume(void)
+{
+	uint32_t clkgr, cppcr, stable;
+
+	cppcr = readl(cgu->base + CGU_REG_CPPCR);
+	cppcr |= BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit);
+	writel(cppcr, cgu->base + CGU_REG_CPPCR);
+
+	stable = BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.stable_bit);
+	do {
+		cppcr = readl(cgu->base + CGU_REG_CPPCR);
+	} while (!(cppcr & stable));
+
+	clkgr = readl(cgu->base + CGU_REG_CLKGR);
+	clkgr &= ~JZ_CLOCK_GATE_TCU;
+	clkgr &= ~JZ_CLOCK_GATE_DMAC;
+	clkgr &= ~JZ_CLOCK_GATE_UART0;
+	writel(clkgr, cgu->base + CGU_REG_CLKGR);
+}
-- 
2.3.5

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

* [PATCH v3 30/37] clk: ingenic: add JZ4780 CGU support
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

Add support for the clocks provided by the CGU in the Ingenic JZ4780
SoC, making use of the SoC-agnostic CGU code to do the heavy lifting.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Co-authored-by: Paul Cercueil <paul@crapouillou.net>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - Remove FSF address per checkpatch (ZubairLK).
---
 drivers/clk/ingenic/Makefile     |   1 +
 drivers/clk/ingenic/jz4780-cgu.c | 732 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 733 insertions(+)
 create mode 100644 drivers/clk/ingenic/jz4780-cgu.c

diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index e6db7da..cd47b06 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -1,2 +1,3 @@
 obj-y				+= cgu.o
 obj-$(CONFIG_MACH_JZ4740)	+= jz4740-cgu.o
+obj-$(CONFIG_MACH_JZ4780)	+= jz4780-cgu.o
diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c
new file mode 100644
index 0000000..d8862ea
--- /dev/null
+++ b/drivers/clk/ingenic/jz4780-cgu.c
@@ -0,0 +1,732 @@
+/*
+ * Ingenic JZ4780 SoC CGU driver
+ *
+ * Copyright (c) 2013-2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <dt-bindings/clock/jz4780-cgu.h>
+#include "cgu.h"
+
+/* CGU register offsets */
+#define CGU_REG_CLOCKCONTROL	0x00
+#define CGU_REG_PLLCONTROL	0x0c
+#define CGU_REG_APLL		0x10
+#define CGU_REG_MPLL		0x14
+#define CGU_REG_EPLL		0x18
+#define CGU_REG_VPLL		0x1c
+#define CGU_REG_CLKGR0		0x20
+#define CGU_REG_OPCR		0x24
+#define CGU_REG_CLKGR1		0x28
+#define CGU_REG_DDRCDR		0x2c
+#define CGU_REG_VPUCDR		0x30
+#define CGU_REG_USBPCR		0x3c
+#define CGU_REG_USBRDT		0x40
+#define CGU_REG_USBVBFIL	0x44
+#define CGU_REG_USBPCR1		0x48
+#define CGU_REG_LP0CDR		0x54
+#define CGU_REG_I2SCDR		0x60
+#define CGU_REG_LP1CDR		0x64
+#define CGU_REG_MSC0CDR		0x68
+#define CGU_REG_UHCCDR		0x6c
+#define CGU_REG_SSICDR		0x74
+#define CGU_REG_CIMCDR		0x7c
+#define CGU_REG_PCMCDR		0x84
+#define CGU_REG_GPUCDR		0x88
+#define CGU_REG_HDMICDR		0x8c
+#define CGU_REG_MSC1CDR		0xa4
+#define CGU_REG_MSC2CDR		0xa8
+#define CGU_REG_BCHCDR		0xac
+#define CGU_REG_CLOCKSTATUS	0xd4
+
+/* bits within the OPCR register */
+#define OPCR_SPENDN0		(1 << 7)
+#define OPCR_SPENDN1		(1 << 6)
+
+/* bits within the USBPCR register */
+#define USBPCR_USB_MODE		BIT(31)
+#define USBPCR_IDPULLUP_MASK	(0x3 << 28)
+#define USBPCR_COMMONONN	BIT(25)
+#define USBPCR_VBUSVLDEXT	BIT(24)
+#define USBPCR_VBUSVLDEXTSEL	BIT(23)
+#define USBPCR_POR		BIT(22)
+#define USBPCR_OTG_DISABLE	BIT(20)
+#define USBPCR_COMPDISTUNE_MASK	(0x7 << 17)
+#define USBPCR_OTGTUNE_MASK	(0x7 << 14)
+#define USBPCR_SQRXTUNE_MASK	(0x7 << 11)
+#define USBPCR_TXFSLSTUNE_MASK	(0xf << 7)
+#define USBPCR_TXPREEMPHTUNE	BIT(6)
+#define USBPCR_TXHSXVTUNE_MASK	(0x3 << 4)
+#define USBPCR_TXVREFTUNE_MASK	0xf
+
+/* bits within the USBPCR1 register */
+#define USBPCR1_REFCLKSEL_SHIFT	26
+#define USBPCR1_REFCLKSEL_MASK	(0x3 << USBPCR1_REFCLKSEL_SHIFT)
+#define USBPCR1_REFCLKSEL_CORE	(0x2 << USBPCR1_REFCLKSEL_SHIFT)
+#define USBPCR1_REFCLKDIV_SHIFT	24
+#define USBPCR1_REFCLKDIV_MASK	(0x3 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_19_2	(0x3 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_48	(0x2 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_24	(0x1 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_12	(0x0 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_USB_SEL		BIT(28)
+#define USBPCR1_WORD_IF0	BIT(19)
+#define USBPCR1_WORD_IF1	BIT(18)
+
+/* bits within the USBRDT register */
+#define USBRDT_VBFIL_LD_EN	BIT(25)
+#define USBRDT_USBRDT_MASK	0x7fffff
+
+/* bits within the USBVBFIL register */
+#define USBVBFIL_IDDIGFIL_SHIFT	16
+#define USBVBFIL_IDDIGFIL_MASK	(0xffff << USBVBFIL_IDDIGFIL_SHIFT)
+#define USBVBFIL_USBVBFIL_MASK	(0xffff)
+
+static struct ingenic_cgu *cgu;
+
+static u8 jz4780_otg_phy_get_parent(struct clk_hw *hw)
+{
+	/* we only use CLKCORE, revisit if that ever changes */
+	return 0;
+}
+
+static int jz4780_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
+{
+	unsigned long flags;
+	u32 usbpcr1;
+
+	if (idx > 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&cgu->power_lock, flags);
+
+	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
+	usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
+	/* we only use CLKCORE */
+	usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
+	writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
+
+	spin_unlock_irqrestore(&cgu->power_lock, flags);
+	return 0;
+}
+
+static unsigned long jz4780_otg_phy_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	u32 usbpcr1;
+	unsigned refclk_div;
+
+	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
+	refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
+
+	switch (refclk_div) {
+	case USBPCR1_REFCLKDIV_12:
+		return 12000000;
+
+	case USBPCR1_REFCLKDIV_24:
+		return 24000000;
+
+	case USBPCR1_REFCLKDIV_48:
+		return 48000000;
+
+	case USBPCR1_REFCLKDIV_19_2:
+		return 19200000;
+	}
+
+	BUG();
+	return parent_rate;
+}
+
+static long jz4780_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
+				      unsigned long *parent_rate)
+{
+	if (req_rate < 15600000)
+		return 12000000;
+
+	if (req_rate < 21600000)
+		return 19200000;
+
+	if (req_rate < 36000000)
+		return 24000000;
+
+	return 48000000;
+}
+
+static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
+				   unsigned long parent_rate)
+{
+	unsigned long flags;
+	u32 usbpcr1, div_bits;
+
+	switch (req_rate) {
+	case 12000000:
+		div_bits = USBPCR1_REFCLKDIV_12;
+		break;
+
+	case 19200000:
+		div_bits = USBPCR1_REFCLKDIV_19_2;
+		break;
+
+	case 24000000:
+		div_bits = USBPCR1_REFCLKDIV_24;
+		break;
+
+	case 48000000:
+		div_bits = USBPCR1_REFCLKDIV_48;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&cgu->power_lock, flags);
+
+	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
+	usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
+	usbpcr1 |= div_bits;
+	writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
+
+	spin_unlock_irqrestore(&cgu->power_lock, flags);
+	return 0;
+}
+
+struct clk_ops jz4780_otg_phy_ops = {
+	.get_parent = jz4780_otg_phy_get_parent,
+	.set_parent = jz4780_otg_phy_set_parent,
+
+	.recalc_rate = jz4780_otg_phy_recalc_rate,
+	.round_rate = jz4780_otg_phy_round_rate,
+	.set_rate = jz4780_otg_phy_set_rate,
+};
+
+static const s8 pll_od_encoding[16] = {
+	0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+	0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+};
+
+static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = {
+
+	/* External clocks */
+
+	[JZ4780_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
+	[JZ4780_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
+
+	/* PLLs */
+
+#define DEF_PLL(name) { \
+	.reg = CGU_REG_ ## name, \
+	.m_shift = 19, \
+	.m_bits = 13, \
+	.m_offset = 1, \
+	.n_shift = 13, \
+	.n_bits = 6, \
+	.n_offset = 1, \
+	.od_shift = 9, \
+	.od_bits = 4, \
+	.od_max = 16, \
+	.od_encoding = pll_od_encoding, \
+	.stable_bit = 6, \
+	.bypass_bit = 1, \
+	.enable_bit = 0, \
+}
+
+	[JZ4780_CLK_APLL] = {
+		"apll", CGU_CLK_PLL,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.pll = DEF_PLL(APLL),
+	},
+
+	[JZ4780_CLK_MPLL] = {
+		"mpll", CGU_CLK_PLL,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.pll = DEF_PLL(MPLL),
+	},
+
+	[JZ4780_CLK_EPLL] = {
+		"epll", CGU_CLK_PLL,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.pll = DEF_PLL(EPLL),
+	},
+
+	[JZ4780_CLK_VPLL] = {
+		"vpll", CGU_CLK_PLL,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.pll = DEF_PLL(VPLL),
+	},
+
+#undef DEF_PLL
+
+	/* Custom (SoC-specific) OTG PHY */
+
+	[JZ4780_CLK_OTGPHY] = {
+		"otg_phy", CGU_CLK_CUSTOM,
+		.parents = { -1, -1, JZ4780_CLK_EXCLK, -1 },
+		.custom = { &jz4780_otg_phy_ops },
+	},
+
+	/* Muxes & dividers */
+
+	[JZ4780_CLK_SCLKA] = {
+		"sclk_a", CGU_CLK_MUX,
+		.parents = { -1, JZ4780_CLK_APLL, JZ4780_CLK_EXCLK,
+			     JZ4780_CLK_RTCLK },
+		.mux = { CGU_REG_CLOCKCONTROL, 30, 2 },
+	},
+
+	[JZ4780_CLK_CPUMUX] = {
+		"cpumux", CGU_CLK_MUX,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL },
+		.mux = { CGU_REG_CLOCKCONTROL, 28, 2 },
+	},
+
+	[JZ4780_CLK_CPU] = {
+		"cpu", CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_CPUMUX, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 0, 4, 22, -1, -1 },
+	},
+
+	[JZ4780_CLK_L2CACHE] = {
+		"l2cache", CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_CPUMUX, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 4, 4, -1, -1, -1 },
+	},
+
+	[JZ4780_CLK_AHB0] = {
+		"ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL },
+		.mux = { CGU_REG_CLOCKCONTROL, 26, 2 },
+		.div = { CGU_REG_CLOCKCONTROL, 8, 4, 21, -1, -1 },
+	},
+
+	[JZ4780_CLK_AHB2PMUX] = {
+		"ahb2_apb_mux", CGU_CLK_MUX,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_RTCLK },
+		.mux = { CGU_REG_CLOCKCONTROL, 24, 2 },
+	},
+
+	[JZ4780_CLK_AHB2] = {
+		"ahb2", CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_AHB2PMUX, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 12, 4, 20, -1, -1 },
+	},
+
+	[JZ4780_CLK_PCLK] = {
+		"pclk", CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_AHB2PMUX, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 16, 4, 20, -1, -1 },
+	},
+
+	[JZ4780_CLK_DDR] = {
+		"ddr", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
+		.mux = { CGU_REG_DDRCDR, 30, 2 },
+		.div = { CGU_REG_DDRCDR, 0, 4, 29, 28, 27 },
+	},
+
+	[JZ4780_CLK_VPU] = {
+		"vpu", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL, -1 },
+		.mux = { CGU_REG_VPUCDR, 30, 2 },
+		.div = { CGU_REG_VPUCDR, 0, 4, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR1, 2 },
+	},
+
+	[JZ4780_CLK_I2SPLL] = {
+		"i2s_pll", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_EPLL, -1 },
+		.mux = { CGU_REG_I2SCDR, 30, 1 },
+		.div = { CGU_REG_I2SCDR, 0, 8, 29, 28, 27 },
+	},
+
+	[JZ4780_CLK_I2S] = {
+		"i2s", CGU_CLK_MUX,
+		.parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_I2SPLL, -1 },
+		.mux = { CGU_REG_I2SCDR, 31, 1 },
+	},
+
+	[JZ4780_CLK_LCD0PIXCLK] = {
+		"lcd0pixclk", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_VPLL, -1 },
+		.mux = { CGU_REG_LP0CDR, 30, 2 },
+		.div = { CGU_REG_LP0CDR, 0, 8, 28, 27, 26 },
+	},
+
+	[JZ4780_CLK_LCD1PIXCLK] = {
+		"lcd1pixclk", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_VPLL, -1 },
+		.mux = { CGU_REG_LP1CDR, 30, 2 },
+		.div = { CGU_REG_LP1CDR, 0, 8, 28, 27, 26 },
+	},
+
+	[JZ4780_CLK_MSCMUX] = {
+		"msc_mux", CGU_CLK_MUX,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
+		.mux = { CGU_REG_MSC0CDR, 30, 2 },
+	},
+
+	[JZ4780_CLK_MSC0] = {
+		"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_MSCMUX, -1 },
+		.div = { CGU_REG_MSC0CDR, 0, 8, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 3 },
+	},
+
+	[JZ4780_CLK_MSC1] = {
+		"msc1", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_MSCMUX, -1 },
+		.div = { CGU_REG_MSC1CDR, 0, 8, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 11 },
+	},
+
+	[JZ4780_CLK_MSC2] = {
+		"msc2", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_MSCMUX, -1 },
+		.div = { CGU_REG_MSC2CDR, 0, 8, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 12 },
+	},
+
+	[JZ4780_CLK_UHC] = {
+		"uhc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL, JZ4780_CLK_OTGPHY },
+		.mux = { CGU_REG_UHCCDR, 30, 2 },
+		.div = { CGU_REG_UHCCDR, 0, 8, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 24 },
+	},
+
+	[JZ4780_CLK_SSIPLL] = {
+		"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
+		.mux = { CGU_REG_SSICDR, 30, 1 },
+		.div = { CGU_REG_SSICDR, 0, 8, 29, 28, 27 },
+	},
+
+	[JZ4780_CLK_SSI] = {
+		"ssi", CGU_CLK_MUX,
+		.parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_SSIPLL, -1 },
+		.mux = { CGU_REG_SSICDR, 31, 1 },
+	},
+
+	[JZ4780_CLK_CIMMCLK] = {
+		"cim_mclk", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
+		.mux = { CGU_REG_CIMCDR, 31, 1 },
+		.div = { CGU_REG_CIMCDR, 0, 8, 30, 29, 28 },
+	},
+
+	[JZ4780_CLK_PCMPLL] = {
+		"pcm_pll", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL, JZ4780_CLK_VPLL },
+		.mux = { CGU_REG_PCMCDR, 29, 2 },
+		.div = { CGU_REG_PCMCDR, 0, 8, 28, 27, 26 },
+	},
+
+	[JZ4780_CLK_PCM] = {
+		"pcm", CGU_CLK_MUX | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_PCMPLL, -1 },
+		.mux = { CGU_REG_PCMCDR, 31, 1 },
+		.gate = { CGU_REG_CLKGR1, 3 },
+	},
+
+	[JZ4780_CLK_GPU] = {
+		"gpu", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL },
+		.mux = { CGU_REG_GPUCDR, 30, 2 },
+		.div = { CGU_REG_GPUCDR, 0, 4, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR1, 4 },
+	},
+
+	[JZ4780_CLK_HDMI] = {
+		"hdmi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_VPLL, -1 },
+		.mux = { CGU_REG_HDMICDR, 30, 2 },
+		.div = { CGU_REG_HDMICDR, 0, 8, 29, 28, 26 },
+		.gate = { CGU_REG_CLKGR1, 9 },
+	},
+
+	[JZ4780_CLK_BCH] = {
+		"bch", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL },
+		.mux = { CGU_REG_BCHCDR, 30, 2 },
+		.div = { CGU_REG_BCHCDR, 0, 4, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 1 },
+	},
+
+	/* Gate-only clocks */
+
+	[JZ4780_CLK_NEMC] = {
+		"nemc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_AHB2, -1 },
+		.gate = { CGU_REG_CLKGR0, 0 },
+	},
+
+	[JZ4780_CLK_OTG0] = {
+		"otg0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 2 },
+	},
+
+	[JZ4780_CLK_SSI0] = {
+		"ssi0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SSI, -1 },
+		.gate = { CGU_REG_CLKGR0, 4 },
+	},
+
+	[JZ4780_CLK_SMB0] = {
+		"smb0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 5 },
+	},
+
+	[JZ4780_CLK_SMB1] = {
+		"smb1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 6 },
+	},
+
+	[JZ4780_CLK_SCC] = {
+		"scc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 7 },
+	},
+
+	[JZ4780_CLK_AIC] = {
+		"aic", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 8 },
+	},
+
+	[JZ4780_CLK_TSSI0] = {
+		"tssi0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 9 },
+	},
+
+	[JZ4780_CLK_OWI] = {
+		"owi", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 10 },
+	},
+
+	[JZ4780_CLK_KBC] = {
+		"kbc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 13 },
+	},
+
+	[JZ4780_CLK_SADC] = {
+		"sadc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 14 },
+	},
+
+	[JZ4780_CLK_UART0] = {
+		"uart0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 15 },
+	},
+
+	[JZ4780_CLK_UART1] = {
+		"uart1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 16 },
+	},
+
+	[JZ4780_CLK_UART2] = {
+		"uart2", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 17 },
+	},
+
+	[JZ4780_CLK_UART3] = {
+		"uart3", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 18 },
+	},
+
+	[JZ4780_CLK_SSI1] = {
+		"ssi1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SSI, -1 },
+		.gate = { CGU_REG_CLKGR0, 19 },
+	},
+
+	[JZ4780_CLK_SSI2] = {
+		"ssi2", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SSI, -1 },
+		.gate = { CGU_REG_CLKGR0, 20 },
+	},
+
+	[JZ4780_CLK_PDMA] = {
+		"pdma", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 21 },
+	},
+
+	[JZ4780_CLK_GPS] = {
+		"gps", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 22 },
+	},
+
+	[JZ4780_CLK_MAC] = {
+		"mac", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 23 },
+	},
+
+	[JZ4780_CLK_SMB2] = {
+		"smb2", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 24 },
+	},
+
+	[JZ4780_CLK_CIM] = {
+		"cim", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 26 },
+	},
+
+	[JZ4780_CLK_LCD] = {
+		"lcd", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 28 },
+	},
+
+	[JZ4780_CLK_TVE] = {
+		"tve", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_LCD, -1 },
+		.gate = { CGU_REG_CLKGR0, 27 },
+	},
+
+	[JZ4780_CLK_IPU] = {
+		"ipu", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 29 },
+	},
+
+	[JZ4780_CLK_DDR0] = {
+		"ddr0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_DDR, -1 },
+		.gate = { CGU_REG_CLKGR0, 30 },
+	},
+
+	[JZ4780_CLK_DDR1] = {
+		"ddr1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_DDR, -1 },
+		.gate = { CGU_REG_CLKGR0, 31 },
+	},
+
+	[JZ4780_CLK_SMB3] = {
+		"smb3", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 0 },
+	},
+
+	[JZ4780_CLK_TSSI1] = {
+		"tssi1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 1 },
+	},
+
+	[JZ4780_CLK_COMPRESS] = {
+		"compress", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 5 },
+	},
+
+	[JZ4780_CLK_AIC1] = {
+		"aic1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 6 },
+	},
+
+	[JZ4780_CLK_GPVLC] = {
+		"gpvlc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 7 },
+	},
+
+	[JZ4780_CLK_OTG1] = {
+		"otg1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 8 },
+	},
+
+	[JZ4780_CLK_UART4] = {
+		"uart4", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 10 },
+	},
+
+	[JZ4780_CLK_AHBMON] = {
+		"ahb_mon", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 11 },
+	},
+
+	[JZ4780_CLK_SMB4] = {
+		"smb4", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 12 },
+	},
+
+	[JZ4780_CLK_DES] = {
+		"des", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 13 },
+	},
+
+	[JZ4780_CLK_X2D] = {
+		"x2d", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 14 },
+	},
+
+	[JZ4780_CLK_CORE1] = {
+		"core1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_CPU, -1 },
+		.gate = { CGU_REG_CLKGR1, 15 },
+	},
+
+};
+
+static void __init jz4780_cgu_init(struct device_node *np)
+{
+	int retval;
+
+	cgu = ingenic_cgu_new(jz4780_cgu_clocks,
+			      ARRAY_SIZE(jz4780_cgu_clocks), np);
+	if (!cgu)
+		pr_err("%s: failed to initialise CGU\n", __func__);
+
+	retval = ingenic_cgu_register_clocks(cgu);
+	if (retval)
+		pr_err("%s: failed to register CGU Clocks\n", __func__);
+
+	clk_set_parent(cgu->clocks.clks[JZ4780_CLK_UHC],
+		       cgu->clocks.clks[JZ4780_CLK_MPLL]);
+}
+CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
-- 
2.3.5

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

* [PATCH v3 30/37] clk: ingenic: add JZ4780 CGU support
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, Mike Turquette

Add support for the clocks provided by the CGU in the Ingenic JZ4780
SoC, making use of the SoC-agnostic CGU code to do the heavy lifting.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Co-authored-by: Paul Cercueil <paul@crapouillou.net>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Mike Turquette <mturquette@linaro.org>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - Remove FSF address per checkpatch (ZubairLK).
---
 drivers/clk/ingenic/Makefile     |   1 +
 drivers/clk/ingenic/jz4780-cgu.c | 732 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 733 insertions(+)
 create mode 100644 drivers/clk/ingenic/jz4780-cgu.c

diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index e6db7da..cd47b06 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -1,2 +1,3 @@
 obj-y				+= cgu.o
 obj-$(CONFIG_MACH_JZ4740)	+= jz4740-cgu.o
+obj-$(CONFIG_MACH_JZ4780)	+= jz4780-cgu.o
diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c
new file mode 100644
index 0000000..d8862ea
--- /dev/null
+++ b/drivers/clk/ingenic/jz4780-cgu.c
@@ -0,0 +1,732 @@
+/*
+ * Ingenic JZ4780 SoC CGU driver
+ *
+ * Copyright (c) 2013-2015 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <dt-bindings/clock/jz4780-cgu.h>
+#include "cgu.h"
+
+/* CGU register offsets */
+#define CGU_REG_CLOCKCONTROL	0x00
+#define CGU_REG_PLLCONTROL	0x0c
+#define CGU_REG_APLL		0x10
+#define CGU_REG_MPLL		0x14
+#define CGU_REG_EPLL		0x18
+#define CGU_REG_VPLL		0x1c
+#define CGU_REG_CLKGR0		0x20
+#define CGU_REG_OPCR		0x24
+#define CGU_REG_CLKGR1		0x28
+#define CGU_REG_DDRCDR		0x2c
+#define CGU_REG_VPUCDR		0x30
+#define CGU_REG_USBPCR		0x3c
+#define CGU_REG_USBRDT		0x40
+#define CGU_REG_USBVBFIL	0x44
+#define CGU_REG_USBPCR1		0x48
+#define CGU_REG_LP0CDR		0x54
+#define CGU_REG_I2SCDR		0x60
+#define CGU_REG_LP1CDR		0x64
+#define CGU_REG_MSC0CDR		0x68
+#define CGU_REG_UHCCDR		0x6c
+#define CGU_REG_SSICDR		0x74
+#define CGU_REG_CIMCDR		0x7c
+#define CGU_REG_PCMCDR		0x84
+#define CGU_REG_GPUCDR		0x88
+#define CGU_REG_HDMICDR		0x8c
+#define CGU_REG_MSC1CDR		0xa4
+#define CGU_REG_MSC2CDR		0xa8
+#define CGU_REG_BCHCDR		0xac
+#define CGU_REG_CLOCKSTATUS	0xd4
+
+/* bits within the OPCR register */
+#define OPCR_SPENDN0		(1 << 7)
+#define OPCR_SPENDN1		(1 << 6)
+
+/* bits within the USBPCR register */
+#define USBPCR_USB_MODE		BIT(31)
+#define USBPCR_IDPULLUP_MASK	(0x3 << 28)
+#define USBPCR_COMMONONN	BIT(25)
+#define USBPCR_VBUSVLDEXT	BIT(24)
+#define USBPCR_VBUSVLDEXTSEL	BIT(23)
+#define USBPCR_POR		BIT(22)
+#define USBPCR_OTG_DISABLE	BIT(20)
+#define USBPCR_COMPDISTUNE_MASK	(0x7 << 17)
+#define USBPCR_OTGTUNE_MASK	(0x7 << 14)
+#define USBPCR_SQRXTUNE_MASK	(0x7 << 11)
+#define USBPCR_TXFSLSTUNE_MASK	(0xf << 7)
+#define USBPCR_TXPREEMPHTUNE	BIT(6)
+#define USBPCR_TXHSXVTUNE_MASK	(0x3 << 4)
+#define USBPCR_TXVREFTUNE_MASK	0xf
+
+/* bits within the USBPCR1 register */
+#define USBPCR1_REFCLKSEL_SHIFT	26
+#define USBPCR1_REFCLKSEL_MASK	(0x3 << USBPCR1_REFCLKSEL_SHIFT)
+#define USBPCR1_REFCLKSEL_CORE	(0x2 << USBPCR1_REFCLKSEL_SHIFT)
+#define USBPCR1_REFCLKDIV_SHIFT	24
+#define USBPCR1_REFCLKDIV_MASK	(0x3 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_19_2	(0x3 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_48	(0x2 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_24	(0x1 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_REFCLKDIV_12	(0x0 << USBPCR1_REFCLKDIV_SHIFT)
+#define USBPCR1_USB_SEL		BIT(28)
+#define USBPCR1_WORD_IF0	BIT(19)
+#define USBPCR1_WORD_IF1	BIT(18)
+
+/* bits within the USBRDT register */
+#define USBRDT_VBFIL_LD_EN	BIT(25)
+#define USBRDT_USBRDT_MASK	0x7fffff
+
+/* bits within the USBVBFIL register */
+#define USBVBFIL_IDDIGFIL_SHIFT	16
+#define USBVBFIL_IDDIGFIL_MASK	(0xffff << USBVBFIL_IDDIGFIL_SHIFT)
+#define USBVBFIL_USBVBFIL_MASK	(0xffff)
+
+static struct ingenic_cgu *cgu;
+
+static u8 jz4780_otg_phy_get_parent(struct clk_hw *hw)
+{
+	/* we only use CLKCORE, revisit if that ever changes */
+	return 0;
+}
+
+static int jz4780_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
+{
+	unsigned long flags;
+	u32 usbpcr1;
+
+	if (idx > 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&cgu->power_lock, flags);
+
+	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
+	usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
+	/* we only use CLKCORE */
+	usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
+	writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
+
+	spin_unlock_irqrestore(&cgu->power_lock, flags);
+	return 0;
+}
+
+static unsigned long jz4780_otg_phy_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	u32 usbpcr1;
+	unsigned refclk_div;
+
+	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
+	refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
+
+	switch (refclk_div) {
+	case USBPCR1_REFCLKDIV_12:
+		return 12000000;
+
+	case USBPCR1_REFCLKDIV_24:
+		return 24000000;
+
+	case USBPCR1_REFCLKDIV_48:
+		return 48000000;
+
+	case USBPCR1_REFCLKDIV_19_2:
+		return 19200000;
+	}
+
+	BUG();
+	return parent_rate;
+}
+
+static long jz4780_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
+				      unsigned long *parent_rate)
+{
+	if (req_rate < 15600000)
+		return 12000000;
+
+	if (req_rate < 21600000)
+		return 19200000;
+
+	if (req_rate < 36000000)
+		return 24000000;
+
+	return 48000000;
+}
+
+static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
+				   unsigned long parent_rate)
+{
+	unsigned long flags;
+	u32 usbpcr1, div_bits;
+
+	switch (req_rate) {
+	case 12000000:
+		div_bits = USBPCR1_REFCLKDIV_12;
+		break;
+
+	case 19200000:
+		div_bits = USBPCR1_REFCLKDIV_19_2;
+		break;
+
+	case 24000000:
+		div_bits = USBPCR1_REFCLKDIV_24;
+		break;
+
+	case 48000000:
+		div_bits = USBPCR1_REFCLKDIV_48;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&cgu->power_lock, flags);
+
+	usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
+	usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
+	usbpcr1 |= div_bits;
+	writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
+
+	spin_unlock_irqrestore(&cgu->power_lock, flags);
+	return 0;
+}
+
+struct clk_ops jz4780_otg_phy_ops = {
+	.get_parent = jz4780_otg_phy_get_parent,
+	.set_parent = jz4780_otg_phy_set_parent,
+
+	.recalc_rate = jz4780_otg_phy_recalc_rate,
+	.round_rate = jz4780_otg_phy_round_rate,
+	.set_rate = jz4780_otg_phy_set_rate,
+};
+
+static const s8 pll_od_encoding[16] = {
+	0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+	0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+};
+
+static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = {
+
+	/* External clocks */
+
+	[JZ4780_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
+	[JZ4780_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
+
+	/* PLLs */
+
+#define DEF_PLL(name) { \
+	.reg = CGU_REG_ ## name, \
+	.m_shift = 19, \
+	.m_bits = 13, \
+	.m_offset = 1, \
+	.n_shift = 13, \
+	.n_bits = 6, \
+	.n_offset = 1, \
+	.od_shift = 9, \
+	.od_bits = 4, \
+	.od_max = 16, \
+	.od_encoding = pll_od_encoding, \
+	.stable_bit = 6, \
+	.bypass_bit = 1, \
+	.enable_bit = 0, \
+}
+
+	[JZ4780_CLK_APLL] = {
+		"apll", CGU_CLK_PLL,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.pll = DEF_PLL(APLL),
+	},
+
+	[JZ4780_CLK_MPLL] = {
+		"mpll", CGU_CLK_PLL,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.pll = DEF_PLL(MPLL),
+	},
+
+	[JZ4780_CLK_EPLL] = {
+		"epll", CGU_CLK_PLL,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.pll = DEF_PLL(EPLL),
+	},
+
+	[JZ4780_CLK_VPLL] = {
+		"vpll", CGU_CLK_PLL,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.pll = DEF_PLL(VPLL),
+	},
+
+#undef DEF_PLL
+
+	/* Custom (SoC-specific) OTG PHY */
+
+	[JZ4780_CLK_OTGPHY] = {
+		"otg_phy", CGU_CLK_CUSTOM,
+		.parents = { -1, -1, JZ4780_CLK_EXCLK, -1 },
+		.custom = { &jz4780_otg_phy_ops },
+	},
+
+	/* Muxes & dividers */
+
+	[JZ4780_CLK_SCLKA] = {
+		"sclk_a", CGU_CLK_MUX,
+		.parents = { -1, JZ4780_CLK_APLL, JZ4780_CLK_EXCLK,
+			     JZ4780_CLK_RTCLK },
+		.mux = { CGU_REG_CLOCKCONTROL, 30, 2 },
+	},
+
+	[JZ4780_CLK_CPUMUX] = {
+		"cpumux", CGU_CLK_MUX,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL },
+		.mux = { CGU_REG_CLOCKCONTROL, 28, 2 },
+	},
+
+	[JZ4780_CLK_CPU] = {
+		"cpu", CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_CPUMUX, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 0, 4, 22, -1, -1 },
+	},
+
+	[JZ4780_CLK_L2CACHE] = {
+		"l2cache", CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_CPUMUX, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 4, 4, -1, -1, -1 },
+	},
+
+	[JZ4780_CLK_AHB0] = {
+		"ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL },
+		.mux = { CGU_REG_CLOCKCONTROL, 26, 2 },
+		.div = { CGU_REG_CLOCKCONTROL, 8, 4, 21, -1, -1 },
+	},
+
+	[JZ4780_CLK_AHB2PMUX] = {
+		"ahb2_apb_mux", CGU_CLK_MUX,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_RTCLK },
+		.mux = { CGU_REG_CLOCKCONTROL, 24, 2 },
+	},
+
+	[JZ4780_CLK_AHB2] = {
+		"ahb2", CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_AHB2PMUX, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 12, 4, 20, -1, -1 },
+	},
+
+	[JZ4780_CLK_PCLK] = {
+		"pclk", CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_AHB2PMUX, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 16, 4, 20, -1, -1 },
+	},
+
+	[JZ4780_CLK_DDR] = {
+		"ddr", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
+		.mux = { CGU_REG_DDRCDR, 30, 2 },
+		.div = { CGU_REG_DDRCDR, 0, 4, 29, 28, 27 },
+	},
+
+	[JZ4780_CLK_VPU] = {
+		"vpu", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL, -1 },
+		.mux = { CGU_REG_VPUCDR, 30, 2 },
+		.div = { CGU_REG_VPUCDR, 0, 4, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR1, 2 },
+	},
+
+	[JZ4780_CLK_I2SPLL] = {
+		"i2s_pll", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_EPLL, -1 },
+		.mux = { CGU_REG_I2SCDR, 30, 1 },
+		.div = { CGU_REG_I2SCDR, 0, 8, 29, 28, 27 },
+	},
+
+	[JZ4780_CLK_I2S] = {
+		"i2s", CGU_CLK_MUX,
+		.parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_I2SPLL, -1 },
+		.mux = { CGU_REG_I2SCDR, 31, 1 },
+	},
+
+	[JZ4780_CLK_LCD0PIXCLK] = {
+		"lcd0pixclk", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_VPLL, -1 },
+		.mux = { CGU_REG_LP0CDR, 30, 2 },
+		.div = { CGU_REG_LP0CDR, 0, 8, 28, 27, 26 },
+	},
+
+	[JZ4780_CLK_LCD1PIXCLK] = {
+		"lcd1pixclk", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_VPLL, -1 },
+		.mux = { CGU_REG_LP1CDR, 30, 2 },
+		.div = { CGU_REG_LP1CDR, 0, 8, 28, 27, 26 },
+	},
+
+	[JZ4780_CLK_MSCMUX] = {
+		"msc_mux", CGU_CLK_MUX,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
+		.mux = { CGU_REG_MSC0CDR, 30, 2 },
+	},
+
+	[JZ4780_CLK_MSC0] = {
+		"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_MSCMUX, -1 },
+		.div = { CGU_REG_MSC0CDR, 0, 8, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 3 },
+	},
+
+	[JZ4780_CLK_MSC1] = {
+		"msc1", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_MSCMUX, -1 },
+		.div = { CGU_REG_MSC1CDR, 0, 8, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 11 },
+	},
+
+	[JZ4780_CLK_MSC2] = {
+		"msc2", CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_MSCMUX, -1 },
+		.div = { CGU_REG_MSC2CDR, 0, 8, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 12 },
+	},
+
+	[JZ4780_CLK_UHC] = {
+		"uhc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL, JZ4780_CLK_OTGPHY },
+		.mux = { CGU_REG_UHCCDR, 30, 2 },
+		.div = { CGU_REG_UHCCDR, 0, 8, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 24 },
+	},
+
+	[JZ4780_CLK_SSIPLL] = {
+		"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
+		.mux = { CGU_REG_SSICDR, 30, 1 },
+		.div = { CGU_REG_SSICDR, 0, 8, 29, 28, 27 },
+	},
+
+	[JZ4780_CLK_SSI] = {
+		"ssi", CGU_CLK_MUX,
+		.parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_SSIPLL, -1 },
+		.mux = { CGU_REG_SSICDR, 31, 1 },
+	},
+
+	[JZ4780_CLK_CIMMCLK] = {
+		"cim_mclk", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
+		.mux = { CGU_REG_CIMCDR, 31, 1 },
+		.div = { CGU_REG_CIMCDR, 0, 8, 30, 29, 28 },
+	},
+
+	[JZ4780_CLK_PCMPLL] = {
+		"pcm_pll", CGU_CLK_MUX | CGU_CLK_DIV,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL, JZ4780_CLK_VPLL },
+		.mux = { CGU_REG_PCMCDR, 29, 2 },
+		.div = { CGU_REG_PCMCDR, 0, 8, 28, 27, 26 },
+	},
+
+	[JZ4780_CLK_PCM] = {
+		"pcm", CGU_CLK_MUX | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_PCMPLL, -1 },
+		.mux = { CGU_REG_PCMCDR, 31, 1 },
+		.gate = { CGU_REG_CLKGR1, 3 },
+	},
+
+	[JZ4780_CLK_GPU] = {
+		"gpu", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL },
+		.mux = { CGU_REG_GPUCDR, 30, 2 },
+		.div = { CGU_REG_GPUCDR, 0, 4, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR1, 4 },
+	},
+
+	[JZ4780_CLK_HDMI] = {
+		"hdmi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_VPLL, -1 },
+		.mux = { CGU_REG_HDMICDR, 30, 2 },
+		.div = { CGU_REG_HDMICDR, 0, 8, 29, 28, 26 },
+		.gate = { CGU_REG_CLKGR1, 9 },
+	},
+
+	[JZ4780_CLK_BCH] = {
+		"bch", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
+			     JZ4780_CLK_EPLL },
+		.mux = { CGU_REG_BCHCDR, 30, 2 },
+		.div = { CGU_REG_BCHCDR, 0, 4, 29, 28, 27 },
+		.gate = { CGU_REG_CLKGR0, 1 },
+	},
+
+	/* Gate-only clocks */
+
+	[JZ4780_CLK_NEMC] = {
+		"nemc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_AHB2, -1 },
+		.gate = { CGU_REG_CLKGR0, 0 },
+	},
+
+	[JZ4780_CLK_OTG0] = {
+		"otg0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 2 },
+	},
+
+	[JZ4780_CLK_SSI0] = {
+		"ssi0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SSI, -1 },
+		.gate = { CGU_REG_CLKGR0, 4 },
+	},
+
+	[JZ4780_CLK_SMB0] = {
+		"smb0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 5 },
+	},
+
+	[JZ4780_CLK_SMB1] = {
+		"smb1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 6 },
+	},
+
+	[JZ4780_CLK_SCC] = {
+		"scc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 7 },
+	},
+
+	[JZ4780_CLK_AIC] = {
+		"aic", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 8 },
+	},
+
+	[JZ4780_CLK_TSSI0] = {
+		"tssi0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 9 },
+	},
+
+	[JZ4780_CLK_OWI] = {
+		"owi", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 10 },
+	},
+
+	[JZ4780_CLK_KBC] = {
+		"kbc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 13 },
+	},
+
+	[JZ4780_CLK_SADC] = {
+		"sadc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 14 },
+	},
+
+	[JZ4780_CLK_UART0] = {
+		"uart0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 15 },
+	},
+
+	[JZ4780_CLK_UART1] = {
+		"uart1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 16 },
+	},
+
+	[JZ4780_CLK_UART2] = {
+		"uart2", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 17 },
+	},
+
+	[JZ4780_CLK_UART3] = {
+		"uart3", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 18 },
+	},
+
+	[JZ4780_CLK_SSI1] = {
+		"ssi1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SSI, -1 },
+		.gate = { CGU_REG_CLKGR0, 19 },
+	},
+
+	[JZ4780_CLK_SSI2] = {
+		"ssi2", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_SSI, -1 },
+		.gate = { CGU_REG_CLKGR0, 20 },
+	},
+
+	[JZ4780_CLK_PDMA] = {
+		"pdma", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 21 },
+	},
+
+	[JZ4780_CLK_GPS] = {
+		"gps", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 22 },
+	},
+
+	[JZ4780_CLK_MAC] = {
+		"mac", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 23 },
+	},
+
+	[JZ4780_CLK_SMB2] = {
+		"smb2", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 24 },
+	},
+
+	[JZ4780_CLK_CIM] = {
+		"cim", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 26 },
+	},
+
+	[JZ4780_CLK_LCD] = {
+		"lcd", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 28 },
+	},
+
+	[JZ4780_CLK_TVE] = {
+		"tve", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_LCD, -1 },
+		.gate = { CGU_REG_CLKGR0, 27 },
+	},
+
+	[JZ4780_CLK_IPU] = {
+		"ipu", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR0, 29 },
+	},
+
+	[JZ4780_CLK_DDR0] = {
+		"ddr0", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_DDR, -1 },
+		.gate = { CGU_REG_CLKGR0, 30 },
+	},
+
+	[JZ4780_CLK_DDR1] = {
+		"ddr1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_DDR, -1 },
+		.gate = { CGU_REG_CLKGR0, 31 },
+	},
+
+	[JZ4780_CLK_SMB3] = {
+		"smb3", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 0 },
+	},
+
+	[JZ4780_CLK_TSSI1] = {
+		"tssi1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 1 },
+	},
+
+	[JZ4780_CLK_COMPRESS] = {
+		"compress", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 5 },
+	},
+
+	[JZ4780_CLK_AIC1] = {
+		"aic1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 6 },
+	},
+
+	[JZ4780_CLK_GPVLC] = {
+		"gpvlc", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 7 },
+	},
+
+	[JZ4780_CLK_OTG1] = {
+		"otg1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 8 },
+	},
+
+	[JZ4780_CLK_UART4] = {
+		"uart4", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 10 },
+	},
+
+	[JZ4780_CLK_AHBMON] = {
+		"ahb_mon", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 11 },
+	},
+
+	[JZ4780_CLK_SMB4] = {
+		"smb4", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_PCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 12 },
+	},
+
+	[JZ4780_CLK_DES] = {
+		"des", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 13 },
+	},
+
+	[JZ4780_CLK_X2D] = {
+		"x2d", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_EXCLK, -1 },
+		.gate = { CGU_REG_CLKGR1, 14 },
+	},
+
+	[JZ4780_CLK_CORE1] = {
+		"core1", CGU_CLK_GATE,
+		.parents = { JZ4780_CLK_CPU, -1 },
+		.gate = { CGU_REG_CLKGR1, 15 },
+	},
+
+};
+
+static void __init jz4780_cgu_init(struct device_node *np)
+{
+	int retval;
+
+	cgu = ingenic_cgu_new(jz4780_cgu_clocks,
+			      ARRAY_SIZE(jz4780_cgu_clocks), np);
+	if (!cgu)
+		pr_err("%s: failed to initialise CGU\n", __func__);
+
+	retval = ingenic_cgu_register_clocks(cgu);
+	if (retval)
+		pr_err("%s: failed to register CGU Clocks\n", __func__);
+
+	clk_set_parent(cgu->clocks.clks[JZ4780_CLK_UHC],
+		       cgu->clocks.clks[JZ4780_CLK_MPLL]);
+}
+CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
-- 
2.3.5

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

* [PATCH v3 31/37] MIPS: JZ4740: remove clock.h
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

The only thing remaining in arch/mips/jz4740/clock.h is declarations of
the jz4740_clock_{suspend,resume} functions. Move these to
arch/mips/include/asm/mach-jz4740/clock.h for consistency with similar
functions, and remove the redundant arch/mips/jz4740/clock.h header.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/clock.h |  3 +++
 arch/mips/jz4740/clock.h                  | 25 -------------------------
 arch/mips/jz4740/pm.c                     |  2 --
 3 files changed, 3 insertions(+), 27 deletions(-)
 delete mode 100644 arch/mips/jz4740/clock.h

diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h
index 16659cd..104d2df 100644
--- a/arch/mips/include/asm/mach-jz4740/clock.h
+++ b/arch/mips/include/asm/mach-jz4740/clock.h
@@ -22,6 +22,9 @@ enum jz4740_wait_mode {
 
 void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode);
 
+void jz4740_clock_suspend(void);
+void jz4740_clock_resume(void);
+
 void jz4740_clock_udc_enable_auto_suspend(void);
 void jz4740_clock_udc_disable_auto_suspend(void);
 
diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h
deleted file mode 100644
index 86a3e01..0000000
--- a/arch/mips/jz4740/clock.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 SoC clock support
- *
- *  This program 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.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __MIPS_JZ4740_CLOCK_H__
-#define __MIPS_JZ4740_CLOCK_H__
-
-#include <linux/clk.h>
-#include <linux/list.h>
-
-void jz4740_clock_suspend(void);
-void jz4740_clock_resume(void);
-
-#endif
diff --git a/arch/mips/jz4740/pm.c b/arch/mips/jz4740/pm.c
index d8e2130..2d8653f 100644
--- a/arch/mips/jz4740/pm.c
+++ b/arch/mips/jz4740/pm.c
@@ -20,8 +20,6 @@
 
 #include <asm/mach-jz4740/clock.h>
 
-#include "clock.h"
-
 static int jz4740_pm_enter(suspend_state_t state)
 {
 	jz4740_clock_suspend();
-- 
2.3.5

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

* [PATCH v3 31/37] MIPS: JZ4740: remove clock.h
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

The only thing remaining in arch/mips/jz4740/clock.h is declarations of
the jz4740_clock_{suspend,resume} functions. Move these to
arch/mips/include/asm/mach-jz4740/clock.h for consistency with similar
functions, and remove the redundant arch/mips/jz4740/clock.h header.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/include/asm/mach-jz4740/clock.h |  3 +++
 arch/mips/jz4740/clock.h                  | 25 -------------------------
 arch/mips/jz4740/pm.c                     |  2 --
 3 files changed, 3 insertions(+), 27 deletions(-)
 delete mode 100644 arch/mips/jz4740/clock.h

diff --git a/arch/mips/include/asm/mach-jz4740/clock.h b/arch/mips/include/asm/mach-jz4740/clock.h
index 16659cd..104d2df 100644
--- a/arch/mips/include/asm/mach-jz4740/clock.h
+++ b/arch/mips/include/asm/mach-jz4740/clock.h
@@ -22,6 +22,9 @@ enum jz4740_wait_mode {
 
 void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode);
 
+void jz4740_clock_suspend(void);
+void jz4740_clock_resume(void);
+
 void jz4740_clock_udc_enable_auto_suspend(void);
 void jz4740_clock_udc_disable_auto_suspend(void);
 
diff --git a/arch/mips/jz4740/clock.h b/arch/mips/jz4740/clock.h
deleted file mode 100644
index 86a3e01..0000000
--- a/arch/mips/jz4740/clock.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 SoC clock support
- *
- *  This program 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.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __MIPS_JZ4740_CLOCK_H__
-#define __MIPS_JZ4740_CLOCK_H__
-
-#include <linux/clk.h>
-#include <linux/list.h>
-
-void jz4740_clock_suspend(void);
-void jz4740_clock_resume(void);
-
-#endif
diff --git a/arch/mips/jz4740/pm.c b/arch/mips/jz4740/pm.c
index d8e2130..2d8653f 100644
--- a/arch/mips/jz4740/pm.c
+++ b/arch/mips/jz4740/pm.c
@@ -20,8 +20,6 @@
 
 #include <asm/mach-jz4740/clock.h>
 
-#include "clock.h"
-
 static int jz4740_pm_enter(suspend_state_t state)
 {
 	jz4740_clock_suspend();
-- 
2.3.5

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

* [PATCH v3 32/37] MIPS: JZ4740: only detect RAM size if not specified in DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Allow a devicetree to specify the memory present in the system rather
than probing it from the memory controller. This both saves the probing
for systems where the amount of memory is fixed, and will simplify the
bringup of later Ingenic SoCs where the memory controller register
layout differs.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/Kconfig         | 1 +
 arch/mips/jz4740/Makefile | 2 ++
 arch/mips/jz4740/setup.c  | 8 +++++++-
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e3c859c..f07a213 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -301,6 +301,7 @@ config MACH_INGENIC
 	select GENERIC_IRQ_CHIP
 	select BUILTIN_DTB
 	select USE_OF
+	select LIBFDT
 
 config LANTIQ
 	bool "Lantiq based platforms"
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 7636432..70a9578 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -7,6 +7,8 @@
 obj-y += prom.o time.o reset.o setup.o \
 	gpio.o platform.o timer.o serial.o
 
+CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
+
 # board specific support
 
 obj-$(CONFIG_JZ4740_QI_LB60)	+= board-qi_lb60.o
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 8c08d7d..1bed3cb 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/irqchip.h>
 #include <linux/kernel.h>
+#include <linux/libfdt.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
@@ -55,9 +56,14 @@ static void __init jz4740_detect_mem(void)
 
 void __init plat_mem_setup(void)
 {
+	int offset;
+
 	jz4740_reset_init();
-	jz4740_detect_mem();
 	__dt_setup_arch(__dtb_start);
+
+	offset = fdt_path_offset(__dtb_start, "/memory");
+	if (offset < 0)
+		jz4740_detect_mem();
 }
 
 void __init device_tree_init(void)
-- 
2.3.5

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

* [PATCH v3 32/37] MIPS: JZ4740: only detect RAM size if not specified in DT
@ 2015-04-21 14:46   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:46 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Allow a devicetree to specify the memory present in the system rather
than probing it from the memory controller. This both saves the probing
for systems where the amount of memory is fixed, and will simplify the
bringup of later Ingenic SoCs where the memory controller register
layout differs.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase.

Changes in v2:
  - None.
---
 arch/mips/Kconfig         | 1 +
 arch/mips/jz4740/Makefile | 2 ++
 arch/mips/jz4740/setup.c  | 8 +++++++-
 3 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e3c859c..f07a213 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -301,6 +301,7 @@ config MACH_INGENIC
 	select GENERIC_IRQ_CHIP
 	select BUILTIN_DTB
 	select USE_OF
+	select LIBFDT
 
 config LANTIQ
 	bool "Lantiq based platforms"
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 7636432..70a9578 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -7,6 +7,8 @@
 obj-y += prom.o time.o reset.o setup.o \
 	gpio.o platform.o timer.o serial.o
 
+CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
+
 # board specific support
 
 obj-$(CONFIG_JZ4740_QI_LB60)	+= board-qi_lb60.o
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 8c08d7d..1bed3cb 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/irqchip.h>
 #include <linux/kernel.h>
+#include <linux/libfdt.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 
@@ -55,9 +56,14 @@ static void __init jz4740_detect_mem(void)
 
 void __init plat_mem_setup(void)
 {
+	int offset;
+
 	jz4740_reset_init();
-	jz4740_detect_mem();
 	__dt_setup_arch(__dtb_start);
+
+	offset = fdt_path_offset(__dtb_start, "/memory");
+	if (offset < 0)
+		jz4740_detect_mem();
 }
 
 void __init device_tree_init(void)
-- 
2.3.5

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

* [PATCH v3 33/37] devicetree: document Ingenic SoC UART binding
  2015-04-21 14:46 ` Paul Burton
  (?)
@ 2015-04-21 14:47     ` Paul Burton
  -1 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips-6z/3iImG2C8G8FEW9MqTrA
  Cc: Paul Burton, Lars-Peter Clausen, devicetree-u79uwXL29TY76Z2rM5mHXA

Add binding documentation for the UARTs found in Ingenic SoCs.

Signed-off-by: Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
Cc: Lars-Peter Clausen <lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
Changes in v3:
  - Merge binding documentation for Ingenic SoCs whose bindings differ
    only by their compatible strings.

Changes in v2:
  - None.
---
 .../devicetree/bindings/serial/ingenic,uart.txt    | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt

diff --git a/Documentation/devicetree/bindings/serial/ingenic,uart.txt b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
new file mode 100644
index 0000000..c2d3b3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
@@ -0,0 +1,22 @@
+* Ingenic SoC UART
+
+Required properties:
+- compatible : "ingenic,jz4740-uart" or "ingenic,jz4780-uart"
+- reg : offset and length of the register set for the device.
+- interrupts : should contain uart interrupt.
+- clocks : phandles to the module & baud clocks.
+- clock-names: tuple listing input clock names.
+	Required elements: "baud", "module"
+
+Example:
+
+uart0: serial@10030000 {
+	compatible = "ingenic,jz4740-uart";
+	reg = <0x10030000 0x100>;
+
+	interrupt-parent = <&intc>;
+	interrupts = <9>;
+
+	clocks = <&ext>, <&cgu JZ4740_CLK_UART0>;
+	clock-names = "baud", "module";
+};
-- 
2.3.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 33/37] devicetree: document Ingenic SoC UART binding
@ 2015-04-21 14:47     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, devicetree

Add binding documentation for the UARTs found in Ingenic SoCs.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - Merge binding documentation for Ingenic SoCs whose bindings differ
    only by their compatible strings.

Changes in v2:
  - None.
---
 .../devicetree/bindings/serial/ingenic,uart.txt    | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt

diff --git a/Documentation/devicetree/bindings/serial/ingenic,uart.txt b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
new file mode 100644
index 0000000..c2d3b3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
@@ -0,0 +1,22 @@
+* Ingenic SoC UART
+
+Required properties:
+- compatible : "ingenic,jz4740-uart" or "ingenic,jz4780-uart"
+- reg : offset and length of the register set for the device.
+- interrupts : should contain uart interrupt.
+- clocks : phandles to the module & baud clocks.
+- clock-names: tuple listing input clock names.
+	Required elements: "baud", "module"
+
+Example:
+
+uart0: serial@10030000 {
+	compatible = "ingenic,jz4740-uart";
+	reg = <0x10030000 0x100>;
+
+	interrupt-parent = <&intc>;
+	interrupts = <9>;
+
+	clocks = <&ext>, <&cgu JZ4740_CLK_UART0>;
+	clock-names = "baud", "module";
+};
-- 
2.3.5

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

* [PATCH v3 33/37] devicetree: document Ingenic SoC UART binding
@ 2015-04-21 14:47     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen, devicetree

Add binding documentation for the UARTs found in Ingenic SoCs.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: devicetree@vger.kernel.org
---
Changes in v3:
  - Merge binding documentation for Ingenic SoCs whose bindings differ
    only by their compatible strings.

Changes in v2:
  - None.
---
 .../devicetree/bindings/serial/ingenic,uart.txt    | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt

diff --git a/Documentation/devicetree/bindings/serial/ingenic,uart.txt b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
new file mode 100644
index 0000000..c2d3b3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
@@ -0,0 +1,22 @@
+* Ingenic SoC UART
+
+Required properties:
+- compatible : "ingenic,jz4740-uart" or "ingenic,jz4780-uart"
+- reg : offset and length of the register set for the device.
+- interrupts : should contain uart interrupt.
+- clocks : phandles to the module & baud clocks.
+- clock-names: tuple listing input clock names.
+	Required elements: "baud", "module"
+
+Example:
+
+uart0: serial@10030000 {
+	compatible = "ingenic,jz4740-uart";
+	reg = <0x10030000 0x100>;
+
+	interrupt-parent = <&intc>;
+	interrupts = <9>;
+
+	clocks = <&ext>, <&cgu JZ4740_CLK_UART0>;
+	clock-names = "baud", "module";
+};
-- 
2.3.5

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

* [PATCH v3 34/37] serial: 8250_ingenic: support for Ingenic SoC UARTs
@ 2015-04-21 14:47   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips
  Cc: Paul Burton, Greg Kroah-Hartman, Lars-Peter Clausen, linux-serial

Introduce a driver suitable for use with the UARTs present in
Ingenic SoCs such as the JZ4740 & JZ4780. These are described as being
ns16550 compatible but aren't quite - they require the setting of an
extra bit in the FCR register to enable the UART module. The serial_out
implementation is the same as that in arch/mips/jz4740/serial.c - which
will shortly be removed.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: linux-serial@vger.kernel.org
---
Changes in v3:
  - s/jz47xx/ingenic/ to reflect Ingenic's naming change for newer SoCs.

  - Support JZ4775.

  - Depend on SERIAL_8250_CONSOLE rather than selecting
    SERIAL_CORE_CONSOLE.

  - Read the UART clock for early consoles from the DT, using libfdt to
    find the node for the fixed rate external clock which drives the UART
    in all known Ingenic SoCs, rather than relying upon a hardcoded
    definition for BASE_BAUD.

Changes in v2:
  - Remove FSF address (ZubairLK).

  - Select SERIAL_CORE_CONSOLE (ZubairLK).
---
 drivers/tty/serial/8250/8250_ingenic.c | 261 +++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig        |   9 ++
 drivers/tty/serial/8250/Makefile       |   3 +
 3 files changed, 273 insertions(+)
 create mode 100644 drivers/tty/serial/8250/8250_ingenic.c

diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
new file mode 100644
index 0000000..8eeadb4
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2010 Lars-Peter Clausen <lars@metafoo.de>
+ * Copyright (C) 2015 Imagination Technologies
+ *
+ * Ingenic SoC UART support
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/libfdt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+
+struct ingenic_uart_data {
+	struct clk	*clk_module;
+	struct clk	*clk_baud;
+	int		line;
+};
+
+#define UART_FCR_UME	BIT(4)
+
+static struct earlycon_device *early_device;
+
+static uint8_t __init early_in(struct uart_port *port, int offset)
+{
+	return readl(port->membase + (offset << 2));
+}
+
+static void __init early_out(struct uart_port *port, int offset, uint8_t value)
+{
+	writel(value, port->membase + (offset << 2));
+}
+
+static void __init ingenic_early_console_putc(struct uart_port *port, int c)
+{
+	uint8_t lsr;
+
+	do {
+		lsr = early_in(port, UART_LSR);
+	} while ((lsr & UART_LSR_TEMT) == 0);
+
+	early_out(port, UART_TX, c);
+}
+
+static void __init ingenic_early_console_write(struct console *console,
+					      const char *s, unsigned int count)
+{
+	uart_console_write(&early_device->port, s, count,
+			   ingenic_early_console_putc);
+}
+
+static void __init ingenic_early_console_setup_clock(struct earlycon_device *dev)
+{
+	void *fdt = initial_boot_params;
+	const __be32 *prop;
+	int offset;
+
+	offset = fdt_path_offset(fdt, "/ext");
+	if (offset < 0)
+		return;
+
+	prop = fdt_getprop(fdt, offset, "clock-frequency", NULL);
+	if (!prop)
+		return;
+
+	dev->port.uartclk = be32_to_cpup(prop);
+}
+
+static int __init ingenic_early_console_setup(struct earlycon_device *dev,
+					      const char *opt)
+{
+	struct uart_port *port = &dev->port;
+	unsigned int baud, divisor;
+
+	if (!dev->port.membase)
+		return -ENODEV;
+
+	ingenic_early_console_setup_clock(dev);
+
+	baud = dev->baud ?: 115200;
+	divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);
+
+	early_out(port, UART_IER, 0);
+	early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8);
+	early_out(port, UART_DLL, 0);
+	early_out(port, UART_DLM, 0);
+	early_out(port, UART_LCR, UART_LCR_WLEN8);
+	early_out(port, UART_FCR, UART_FCR_UME | UART_FCR_CLEAR_XMIT |
+			UART_FCR_CLEAR_RCVR | UART_FCR_ENABLE_FIFO);
+	early_out(port, UART_MCR, UART_MCR_RTS | UART_MCR_DTR);
+
+	early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8);
+	early_out(port, UART_DLL, divisor & 0xff);
+	early_out(port, UART_DLM, (divisor >> 8) & 0xff);
+	early_out(port, UART_LCR, UART_LCR_WLEN8);
+
+	early_device = dev;
+	dev->con->write = ingenic_early_console_write;
+
+	return 0;
+}
+
+EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup);
+OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart",
+		    ingenic_early_console_setup);
+
+EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup);
+OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart",
+		    ingenic_early_console_setup);
+
+EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup);
+OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
+		    ingenic_early_console_setup);
+
+static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
+{
+	switch (offset) {
+	case UART_FCR:
+		/* UART module enable */
+		value |= UART_FCR_UME;
+		break;
+
+	case UART_IER:
+		value |= (value & 0x4) << 2;
+		break;
+
+	default:
+		break;
+	}
+
+	writeb(value, p->membase + (offset << p->regshift));
+}
+
+static int ingenic_uart_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	struct ingenic_uart_data *data;
+	int err;
+
+	if (!regs || !irq) {
+		dev_err(&pdev->dev, "no registers/irq defined\n");
+		return -EINVAL;
+	}
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	spin_lock_init(&uart.port.lock);
+	uart.port.type = PORT_16550;
+	uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = regs->start;
+	uart.port.regshift = 2;
+	uart.port.serial_out = ingenic_uart_serial_out;
+	uart.port.irq = irq->start;
+	uart.port.dev = &pdev->dev;
+
+	uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
+					 resource_size(regs));
+	if (!uart.port.membase)
+		return -ENOMEM;
+
+	data->clk_module = devm_clk_get(&pdev->dev, "module");
+	if (IS_ERR(data->clk_module)) {
+		err = PTR_ERR(data->clk_module);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"unable to get module clock: %d\n", err);
+		return err;
+	}
+
+	data->clk_baud = devm_clk_get(&pdev->dev, "baud");
+	if (IS_ERR(data->clk_baud)) {
+		err = PTR_ERR(data->clk_baud);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"unable to get baud clock: %d\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(data->clk_module);
+	if (err) {
+		dev_err(&pdev->dev, "could not enable module clock: %d\n", err);
+		goto out;
+	}
+
+	err = clk_prepare_enable(data->clk_baud);
+	if (err) {
+		dev_err(&pdev->dev, "could not enable baud clock: %d\n", err);
+		goto out_disable_moduleclk;
+	}
+	uart.port.uartclk = clk_get_rate(data->clk_baud);
+
+	data->line = serial8250_register_8250_port(&uart);
+	if (data->line < 0) {
+		err = data->line;
+		goto out_disable_baudclk;
+	}
+
+	platform_set_drvdata(pdev, data);
+	return 0;
+
+out_disable_baudclk:
+	clk_disable_unprepare(data->clk_baud);
+out_disable_moduleclk:
+	clk_disable_unprepare(data->clk_module);
+out:
+	return err;
+}
+
+static int ingenic_uart_remove(struct platform_device *pdev)
+{
+	struct ingenic_uart_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+	clk_disable_unprepare(data->clk_module);
+	clk_disable_unprepare(data->clk_baud);
+	return 0;
+}
+
+static const struct of_device_id of_match[] = {
+	{ .compatible = "ingenic,jz4740-uart" },
+	{ .compatible = "ingenic,jz4775-uart" },
+	{ .compatible = "ingenic,jz4780-uart" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match);
+
+static struct platform_driver ingenic_uart_platform_driver = {
+	.driver = {
+		.name		= "ingenic-uart",
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_match,
+	},
+	.probe			= ingenic_uart_probe,
+	.remove			= ingenic_uart_remove,
+};
+
+module_platform_driver(ingenic_uart_platform_driver);
+
+MODULE_AUTHOR("Paul Burton");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Ingenic SoC UART driver");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index c350703..43330ea 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -342,3 +342,12 @@ config SERIAL_8250_MT6577
 	help
 	  If you have a Mediatek based board and want to use the
 	  serial port, say Y to this option. If unsure, say N.
+
+config SERIAL_8250_INGENIC
+	bool "Support for Ingenic SoC serial ports"
+	depends on SERIAL_8250_CONSOLE && OF_FLATTREE
+	select LIBFDT
+	select SERIAL_EARLYCON
+	help
+	  If you have a system using an Ingenic SoC and wish to make use of
+	  its UARTs, say Y to this option. If unsure, say N.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 31e7cdc..98fba26 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -23,3 +23,6 @@ obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
 obj-$(CONFIG_SERIAL_8250_OMAP)		+= 8250_omap.o
 obj-$(CONFIG_SERIAL_8250_FINTEK)	+= 8250_fintek.o
 obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
+obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
+
+CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.3.5

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

* [PATCH v3 34/37] serial: 8250_ingenic: support for Ingenic SoC UARTs
@ 2015-04-21 14:47   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips
  Cc: Paul Burton, Greg Kroah-Hartman, Lars-Peter Clausen, linux-serial

Introduce a driver suitable for use with the UARTs present in
Ingenic SoCs such as the JZ4740 & JZ4780. These are described as being
ns16550 compatible but aren't quite - they require the setting of an
extra bit in the FCR register to enable the UART module. The serial_out
implementation is the same as that in arch/mips/jz4740/serial.c - which
will shortly be removed.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: linux-serial@vger.kernel.org
---
Changes in v3:
  - s/jz47xx/ingenic/ to reflect Ingenic's naming change for newer SoCs.

  - Support JZ4775.

  - Depend on SERIAL_8250_CONSOLE rather than selecting
    SERIAL_CORE_CONSOLE.

  - Read the UART clock for early consoles from the DT, using libfdt to
    find the node for the fixed rate external clock which drives the UART
    in all known Ingenic SoCs, rather than relying upon a hardcoded
    definition for BASE_BAUD.

Changes in v2:
  - Remove FSF address (ZubairLK).

  - Select SERIAL_CORE_CONSOLE (ZubairLK).
---
 drivers/tty/serial/8250/8250_ingenic.c | 261 +++++++++++++++++++++++++++++++++
 drivers/tty/serial/8250/Kconfig        |   9 ++
 drivers/tty/serial/8250/Makefile       |   3 +
 3 files changed, 273 insertions(+)
 create mode 100644 drivers/tty/serial/8250/8250_ingenic.c

diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
new file mode 100644
index 0000000..8eeadb4
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2010 Lars-Peter Clausen <lars@metafoo.de>
+ * Copyright (C) 2015 Imagination Technologies
+ *
+ * Ingenic SoC UART support
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/clk.h>
+#include <linux/console.h>
+#include <linux/io.h>
+#include <linux/libfdt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+
+struct ingenic_uart_data {
+	struct clk	*clk_module;
+	struct clk	*clk_baud;
+	int		line;
+};
+
+#define UART_FCR_UME	BIT(4)
+
+static struct earlycon_device *early_device;
+
+static uint8_t __init early_in(struct uart_port *port, int offset)
+{
+	return readl(port->membase + (offset << 2));
+}
+
+static void __init early_out(struct uart_port *port, int offset, uint8_t value)
+{
+	writel(value, port->membase + (offset << 2));
+}
+
+static void __init ingenic_early_console_putc(struct uart_port *port, int c)
+{
+	uint8_t lsr;
+
+	do {
+		lsr = early_in(port, UART_LSR);
+	} while ((lsr & UART_LSR_TEMT) == 0);
+
+	early_out(port, UART_TX, c);
+}
+
+static void __init ingenic_early_console_write(struct console *console,
+					      const char *s, unsigned int count)
+{
+	uart_console_write(&early_device->port, s, count,
+			   ingenic_early_console_putc);
+}
+
+static void __init ingenic_early_console_setup_clock(struct earlycon_device *dev)
+{
+	void *fdt = initial_boot_params;
+	const __be32 *prop;
+	int offset;
+
+	offset = fdt_path_offset(fdt, "/ext");
+	if (offset < 0)
+		return;
+
+	prop = fdt_getprop(fdt, offset, "clock-frequency", NULL);
+	if (!prop)
+		return;
+
+	dev->port.uartclk = be32_to_cpup(prop);
+}
+
+static int __init ingenic_early_console_setup(struct earlycon_device *dev,
+					      const char *opt)
+{
+	struct uart_port *port = &dev->port;
+	unsigned int baud, divisor;
+
+	if (!dev->port.membase)
+		return -ENODEV;
+
+	ingenic_early_console_setup_clock(dev);
+
+	baud = dev->baud ?: 115200;
+	divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);
+
+	early_out(port, UART_IER, 0);
+	early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8);
+	early_out(port, UART_DLL, 0);
+	early_out(port, UART_DLM, 0);
+	early_out(port, UART_LCR, UART_LCR_WLEN8);
+	early_out(port, UART_FCR, UART_FCR_UME | UART_FCR_CLEAR_XMIT |
+			UART_FCR_CLEAR_RCVR | UART_FCR_ENABLE_FIFO);
+	early_out(port, UART_MCR, UART_MCR_RTS | UART_MCR_DTR);
+
+	early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8);
+	early_out(port, UART_DLL, divisor & 0xff);
+	early_out(port, UART_DLM, (divisor >> 8) & 0xff);
+	early_out(port, UART_LCR, UART_LCR_WLEN8);
+
+	early_device = dev;
+	dev->con->write = ingenic_early_console_write;
+
+	return 0;
+}
+
+EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup);
+OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart",
+		    ingenic_early_console_setup);
+
+EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup);
+OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart",
+		    ingenic_early_console_setup);
+
+EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup);
+OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
+		    ingenic_early_console_setup);
+
+static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
+{
+	switch (offset) {
+	case UART_FCR:
+		/* UART module enable */
+		value |= UART_FCR_UME;
+		break;
+
+	case UART_IER:
+		value |= (value & 0x4) << 2;
+		break;
+
+	default:
+		break;
+	}
+
+	writeb(value, p->membase + (offset << p->regshift));
+}
+
+static int ingenic_uart_probe(struct platform_device *pdev)
+{
+	struct uart_8250_port uart = {};
+	struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	struct ingenic_uart_data *data;
+	int err;
+
+	if (!regs || !irq) {
+		dev_err(&pdev->dev, "no registers/irq defined\n");
+		return -EINVAL;
+	}
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	spin_lock_init(&uart.port.lock);
+	uart.port.type = PORT_16550;
+	uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
+	uart.port.iotype = UPIO_MEM;
+	uart.port.mapbase = regs->start;
+	uart.port.regshift = 2;
+	uart.port.serial_out = ingenic_uart_serial_out;
+	uart.port.irq = irq->start;
+	uart.port.dev = &pdev->dev;
+
+	uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
+					 resource_size(regs));
+	if (!uart.port.membase)
+		return -ENOMEM;
+
+	data->clk_module = devm_clk_get(&pdev->dev, "module");
+	if (IS_ERR(data->clk_module)) {
+		err = PTR_ERR(data->clk_module);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"unable to get module clock: %d\n", err);
+		return err;
+	}
+
+	data->clk_baud = devm_clk_get(&pdev->dev, "baud");
+	if (IS_ERR(data->clk_baud)) {
+		err = PTR_ERR(data->clk_baud);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"unable to get baud clock: %d\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(data->clk_module);
+	if (err) {
+		dev_err(&pdev->dev, "could not enable module clock: %d\n", err);
+		goto out;
+	}
+
+	err = clk_prepare_enable(data->clk_baud);
+	if (err) {
+		dev_err(&pdev->dev, "could not enable baud clock: %d\n", err);
+		goto out_disable_moduleclk;
+	}
+	uart.port.uartclk = clk_get_rate(data->clk_baud);
+
+	data->line = serial8250_register_8250_port(&uart);
+	if (data->line < 0) {
+		err = data->line;
+		goto out_disable_baudclk;
+	}
+
+	platform_set_drvdata(pdev, data);
+	return 0;
+
+out_disable_baudclk:
+	clk_disable_unprepare(data->clk_baud);
+out_disable_moduleclk:
+	clk_disable_unprepare(data->clk_module);
+out:
+	return err;
+}
+
+static int ingenic_uart_remove(struct platform_device *pdev)
+{
+	struct ingenic_uart_data *data = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(data->line);
+	clk_disable_unprepare(data->clk_module);
+	clk_disable_unprepare(data->clk_baud);
+	return 0;
+}
+
+static const struct of_device_id of_match[] = {
+	{ .compatible = "ingenic,jz4740-uart" },
+	{ .compatible = "ingenic,jz4775-uart" },
+	{ .compatible = "ingenic,jz4780-uart" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, of_match);
+
+static struct platform_driver ingenic_uart_platform_driver = {
+	.driver = {
+		.name		= "ingenic-uart",
+		.owner		= THIS_MODULE,
+		.of_match_table	= of_match,
+	},
+	.probe			= ingenic_uart_probe,
+	.remove			= ingenic_uart_remove,
+};
+
+module_platform_driver(ingenic_uart_platform_driver);
+
+MODULE_AUTHOR("Paul Burton");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Ingenic SoC UART driver");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index c350703..43330ea 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -342,3 +342,12 @@ config SERIAL_8250_MT6577
 	help
 	  If you have a Mediatek based board and want to use the
 	  serial port, say Y to this option. If unsure, say N.
+
+config SERIAL_8250_INGENIC
+	bool "Support for Ingenic SoC serial ports"
+	depends on SERIAL_8250_CONSOLE && OF_FLATTREE
+	select LIBFDT
+	select SERIAL_EARLYCON
+	help
+	  If you have a system using an Ingenic SoC and wish to make use of
+	  its UARTs, say Y to this option. If unsure, say N.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 31e7cdc..98fba26 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -23,3 +23,6 @@ obj-$(CONFIG_SERIAL_8250_EM)		+= 8250_em.o
 obj-$(CONFIG_SERIAL_8250_OMAP)		+= 8250_omap.o
 obj-$(CONFIG_SERIAL_8250_FINTEK)	+= 8250_fintek.o
 obj-$(CONFIG_SERIAL_8250_MT6577)	+= 8250_mtk.o
+obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o
+
+CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
-- 
2.3.5

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

* [PATCH v3 35/37] MIPS: JZ4740: use Ingenic SoC UART driver
@ 2015-04-21 14:47   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Remove the serial support from arch/mips/jz4740 & make use of the new
Ingenic SoC UART driver. This is done for both regular & early console
output.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Enable the UART driver in qi_lb60_defconfig to preserve its current
    behaviour.

Changes in v2:
  - None.
---
 arch/mips/Kconfig                            |  1 -
 arch/mips/boot/dts/ingenic/jz4740.dtsi       | 22 ++++++++++++++
 arch/mips/boot/dts/ingenic/qi_lb60.dts       |  4 +++
 arch/mips/configs/qi_lb60_defconfig          |  1 +
 arch/mips/include/asm/mach-jz4740/platform.h |  2 --
 arch/mips/jz4740/Makefile                    |  2 +-
 arch/mips/jz4740/board-qi_lb60.c             |  2 --
 arch/mips/jz4740/platform.c                  | 45 ----------------------------
 arch/mips/jz4740/prom.c                      | 13 --------
 arch/mips/jz4740/serial.c                    | 33 --------------------
 arch/mips/jz4740/serial.h                    | 23 --------------
 11 files changed, 28 insertions(+), 120 deletions(-)
 delete mode 100644 arch/mips/jz4740/serial.c
 delete mode 100644 arch/mips/jz4740/serial.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f07a213..01045fb 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -296,7 +296,6 @@ config MACH_INGENIC
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select ARCH_REQUIRE_GPIOLIB
-	select SYS_HAS_EARLY_PRINTK
 	select COMMON_CLK
 	select GENERIC_IRQ_CHIP
 	select BUILTIN_DTB
diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index ef679b4..c52d92d 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -43,4 +43,26 @@
 
 		#clock-cells = <1>;
 	};
+
+	uart0: serial@10030000 {
+		compatible = "ingenic,jz4740-uart";
+		reg = <0x10030000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <9>;
+
+		clocks = <&ext>, <&cgu JZ4740_CLK_UART0>;
+		clock-names = "baud", "module";
+	};
+
+	uart1: serial@10031000 {
+		compatible = "ingenic,jz4740-uart";
+		reg = <0x10031000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <8>;
+
+		clocks = <&ext>, <&cgu JZ4740_CLK_UART1>;
+		clock-names = "baud", "module";
+	};
 };
diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts
index 106d13c..2414d63 100644
--- a/arch/mips/boot/dts/ingenic/qi_lb60.dts
+++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -4,6 +4,10 @@
 
 / {
 	compatible = "qi,lb60", "ingenic,jz4740";
+
+	chosen {
+		stdout-path = &uart0;
+	};
 };
 
 &ext {
diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig
index 1139b89..d7bb8cc 100644
--- a/arch/mips/configs/qi_lb60_defconfig
+++ b/arch/mips/configs/qi_lb60_defconfig
@@ -66,6 +66,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_DMA is not set
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_INGENIC=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_SPI=y
 CONFIG_SPI_GPIO=y
diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h
index 069b43a..32cfbe6 100644
--- a/arch/mips/include/asm/mach-jz4740/platform.h
+++ b/arch/mips/include/asm/mach-jz4740/platform.h
@@ -35,6 +35,4 @@ extern struct platform_device jz4740_wdt_device;
 extern struct platform_device jz4740_pwm_device;
 extern struct platform_device jz4740_dma_device;
 
-void jz4740_serial_device_register(void);
-
 #endif
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 70a9578..89ce401 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -5,7 +5,7 @@
 # Object file lists.
 
 obj-y += prom.o time.o reset.o setup.o \
-	gpio.o platform.o timer.o serial.o
+	gpio.o platform.o timer.o
 
 CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
 
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 21b034c..4e62bf8 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -482,8 +482,6 @@ static int __init qi_lb60_init_platform_devices(void)
 	gpiod_add_lookup_table(&qi_lb60_audio_gpio_table);
 	gpiod_add_lookup_table(&qi_lb60_nand_gpio_table);
 
-	jz4740_serial_device_register();
-
 	spi_register_board_info(qi_lb60_spi_board_info,
 				ARRAY_SIZE(qi_lb60_spi_board_info));
 
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index 2a5c7c7..e8a463b 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -30,7 +30,6 @@
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 
-#include "serial.h"
 #include "clock.h"
 
 /* OHCI controller */
@@ -280,50 +279,6 @@ struct platform_device jz4740_adc_device = {
 	.resource	= jz4740_adc_resources,
 };
 
-/* Serial */
-#define JZ4740_UART_DATA(_id) \
-	{ \
-		.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE, \
-		.iotype = UPIO_MEM, \
-		.regshift = 2, \
-		.serial_out = jz4740_serial_out, \
-		.type = PORT_16550, \
-		.mapbase = JZ4740_UART ## _id ## _BASE_ADDR, \
-		.irq = JZ4740_IRQ_UART ## _id, \
-	}
-
-static struct plat_serial8250_port jz4740_uart_data[] = {
-	JZ4740_UART_DATA(0),
-	JZ4740_UART_DATA(1),
-	{},
-};
-
-static struct platform_device jz4740_uart_device = {
-	.name = "serial8250",
-	.id = 0,
-	.dev = {
-		.platform_data = jz4740_uart_data,
-	},
-};
-
-void jz4740_serial_device_register(void)
-{
-	struct plat_serial8250_port *p;
-	struct clk *ext_clk;
-	unsigned long ext_rate;
-
-	ext_clk = clk_get(NULL, "ext");
-	if (IS_ERR(ext_clk))
-		panic("unable to get ext clock");
-	ext_rate = clk_get_rate(ext_clk);
-	clk_put(ext_clk);
-
-	for (p = jz4740_uart_data; p->flags != 0; ++p)
-		p->uartclk = ext_rate;
-
-	platform_device_register(&jz4740_uart_device);
-}
-
 /* Watchdog */
 static struct resource jz4740_wdt_resources[] = {
 	{
diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
index 5a93f38..6984683 100644
--- a/arch/mips/jz4740/prom.c
+++ b/arch/mips/jz4740/prom.c
@@ -53,16 +53,3 @@ void __init prom_init(void)
 void __init prom_free_prom_memory(void)
 {
 }
-
-#define UART_REG(_reg) ((void __iomem *)CKSEG1ADDR(JZ4740_UART0_BASE_ADDR + (_reg << 2)))
-
-void prom_putchar(char c)
-{
-	uint8_t lsr;
-
-	do {
-		lsr = readb(UART_REG(UART_LSR));
-	} while ((lsr & UART_LSR_TEMT) == 0);
-
-	writeb(c, UART_REG(UART_TX));
-}
diff --git a/arch/mips/jz4740/serial.c b/arch/mips/jz4740/serial.c
deleted file mode 100644
index d23de45..0000000
--- a/arch/mips/jz4740/serial.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 serial support
- *
- *  This program 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.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/io.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-
-void jz4740_serial_out(struct uart_port *p, int offset, int value)
-{
-	switch (offset) {
-	case UART_FCR:
-		value |= 0x10; /* Enable uart module */
-		break;
-	case UART_IER:
-		value |= (value & 0x4) << 2;
-		break;
-	default:
-		break;
-	}
-	writeb(value, p->membase + (offset << p->regshift));
-}
diff --git a/arch/mips/jz4740/serial.h b/arch/mips/jz4740/serial.h
deleted file mode 100644
index 8eb715b..0000000
--- a/arch/mips/jz4740/serial.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 serial support
- *
- *  This program 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.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __MIPS_JZ4740_SERIAL_H__
-#define __MIPS_JZ4740_SERIAL_H__
-
-struct uart_port;
-
-void jz4740_serial_out(struct uart_port *p, int offset, int value);
-
-#endif
-- 
2.3.5

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

* [PATCH v3 35/37] MIPS: JZ4740: use Ingenic SoC UART driver
@ 2015-04-21 14:47   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Remove the serial support from arch/mips/jz4740 & make use of the new
Ingenic SoC UART driver. This is done for both regular & early console
output.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Enable the UART driver in qi_lb60_defconfig to preserve its current
    behaviour.

Changes in v2:
  - None.
---
 arch/mips/Kconfig                            |  1 -
 arch/mips/boot/dts/ingenic/jz4740.dtsi       | 22 ++++++++++++++
 arch/mips/boot/dts/ingenic/qi_lb60.dts       |  4 +++
 arch/mips/configs/qi_lb60_defconfig          |  1 +
 arch/mips/include/asm/mach-jz4740/platform.h |  2 --
 arch/mips/jz4740/Makefile                    |  2 +-
 arch/mips/jz4740/board-qi_lb60.c             |  2 --
 arch/mips/jz4740/platform.c                  | 45 ----------------------------
 arch/mips/jz4740/prom.c                      | 13 --------
 arch/mips/jz4740/serial.c                    | 33 --------------------
 arch/mips/jz4740/serial.h                    | 23 --------------
 11 files changed, 28 insertions(+), 120 deletions(-)
 delete mode 100644 arch/mips/jz4740/serial.c
 delete mode 100644 arch/mips/jz4740/serial.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f07a213..01045fb 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -296,7 +296,6 @@ config MACH_INGENIC
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select ARCH_REQUIRE_GPIOLIB
-	select SYS_HAS_EARLY_PRINTK
 	select COMMON_CLK
 	select GENERIC_IRQ_CHIP
 	select BUILTIN_DTB
diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index ef679b4..c52d92d 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -43,4 +43,26 @@
 
 		#clock-cells = <1>;
 	};
+
+	uart0: serial@10030000 {
+		compatible = "ingenic,jz4740-uart";
+		reg = <0x10030000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <9>;
+
+		clocks = <&ext>, <&cgu JZ4740_CLK_UART0>;
+		clock-names = "baud", "module";
+	};
+
+	uart1: serial@10031000 {
+		compatible = "ingenic,jz4740-uart";
+		reg = <0x10031000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <8>;
+
+		clocks = <&ext>, <&cgu JZ4740_CLK_UART1>;
+		clock-names = "baud", "module";
+	};
 };
diff --git a/arch/mips/boot/dts/ingenic/qi_lb60.dts b/arch/mips/boot/dts/ingenic/qi_lb60.dts
index 106d13c..2414d63 100644
--- a/arch/mips/boot/dts/ingenic/qi_lb60.dts
+++ b/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -4,6 +4,10 @@
 
 / {
 	compatible = "qi,lb60", "ingenic,jz4740";
+
+	chosen {
+		stdout-path = &uart0;
+	};
 };
 
 &ext {
diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig
index 1139b89..d7bb8cc 100644
--- a/arch/mips/configs/qi_lb60_defconfig
+++ b/arch/mips/configs/qi_lb60_defconfig
@@ -66,6 +66,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_DMA is not set
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_INGENIC=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_SPI=y
 CONFIG_SPI_GPIO=y
diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h
index 069b43a..32cfbe6 100644
--- a/arch/mips/include/asm/mach-jz4740/platform.h
+++ b/arch/mips/include/asm/mach-jz4740/platform.h
@@ -35,6 +35,4 @@ extern struct platform_device jz4740_wdt_device;
 extern struct platform_device jz4740_pwm_device;
 extern struct platform_device jz4740_dma_device;
 
-void jz4740_serial_device_register(void);
-
 #endif
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 70a9578..89ce401 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -5,7 +5,7 @@
 # Object file lists.
 
 obj-y += prom.o time.o reset.o setup.o \
-	gpio.o platform.o timer.o serial.o
+	gpio.o platform.o timer.o
 
 CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
 
diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
index 21b034c..4e62bf8 100644
--- a/arch/mips/jz4740/board-qi_lb60.c
+++ b/arch/mips/jz4740/board-qi_lb60.c
@@ -482,8 +482,6 @@ static int __init qi_lb60_init_platform_devices(void)
 	gpiod_add_lookup_table(&qi_lb60_audio_gpio_table);
 	gpiod_add_lookup_table(&qi_lb60_nand_gpio_table);
 
-	jz4740_serial_device_register();
-
 	spi_register_board_info(qi_lb60_spi_board_info,
 				ARRAY_SIZE(qi_lb60_spi_board_info));
 
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index 2a5c7c7..e8a463b 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -30,7 +30,6 @@
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 
-#include "serial.h"
 #include "clock.h"
 
 /* OHCI controller */
@@ -280,50 +279,6 @@ struct platform_device jz4740_adc_device = {
 	.resource	= jz4740_adc_resources,
 };
 
-/* Serial */
-#define JZ4740_UART_DATA(_id) \
-	{ \
-		.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE, \
-		.iotype = UPIO_MEM, \
-		.regshift = 2, \
-		.serial_out = jz4740_serial_out, \
-		.type = PORT_16550, \
-		.mapbase = JZ4740_UART ## _id ## _BASE_ADDR, \
-		.irq = JZ4740_IRQ_UART ## _id, \
-	}
-
-static struct plat_serial8250_port jz4740_uart_data[] = {
-	JZ4740_UART_DATA(0),
-	JZ4740_UART_DATA(1),
-	{},
-};
-
-static struct platform_device jz4740_uart_device = {
-	.name = "serial8250",
-	.id = 0,
-	.dev = {
-		.platform_data = jz4740_uart_data,
-	},
-};
-
-void jz4740_serial_device_register(void)
-{
-	struct plat_serial8250_port *p;
-	struct clk *ext_clk;
-	unsigned long ext_rate;
-
-	ext_clk = clk_get(NULL, "ext");
-	if (IS_ERR(ext_clk))
-		panic("unable to get ext clock");
-	ext_rate = clk_get_rate(ext_clk);
-	clk_put(ext_clk);
-
-	for (p = jz4740_uart_data; p->flags != 0; ++p)
-		p->uartclk = ext_rate;
-
-	platform_device_register(&jz4740_uart_device);
-}
-
 /* Watchdog */
 static struct resource jz4740_wdt_resources[] = {
 	{
diff --git a/arch/mips/jz4740/prom.c b/arch/mips/jz4740/prom.c
index 5a93f38..6984683 100644
--- a/arch/mips/jz4740/prom.c
+++ b/arch/mips/jz4740/prom.c
@@ -53,16 +53,3 @@ void __init prom_init(void)
 void __init prom_free_prom_memory(void)
 {
 }
-
-#define UART_REG(_reg) ((void __iomem *)CKSEG1ADDR(JZ4740_UART0_BASE_ADDR + (_reg << 2)))
-
-void prom_putchar(char c)
-{
-	uint8_t lsr;
-
-	do {
-		lsr = readb(UART_REG(UART_LSR));
-	} while ((lsr & UART_LSR_TEMT) == 0);
-
-	writeb(c, UART_REG(UART_TX));
-}
diff --git a/arch/mips/jz4740/serial.c b/arch/mips/jz4740/serial.c
deleted file mode 100644
index d23de45..0000000
--- a/arch/mips/jz4740/serial.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 serial support
- *
- *  This program 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.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/io.h>
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-
-void jz4740_serial_out(struct uart_port *p, int offset, int value)
-{
-	switch (offset) {
-	case UART_FCR:
-		value |= 0x10; /* Enable uart module */
-		break;
-	case UART_IER:
-		value |= (value & 0x4) << 2;
-		break;
-	default:
-		break;
-	}
-	writeb(value, p->membase + (offset << p->regshift));
-}
diff --git a/arch/mips/jz4740/serial.h b/arch/mips/jz4740/serial.h
deleted file mode 100644
index 8eb715b..0000000
--- a/arch/mips/jz4740/serial.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *  JZ4740 serial support
- *
- *  This program 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.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __MIPS_JZ4740_SERIAL_H__
-#define __MIPS_JZ4740_SERIAL_H__
-
-struct uart_port;
-
-void jz4740_serial_out(struct uart_port *p, int offset, int value);
-
-#endif
-- 
2.3.5

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

* [PATCH v3 36/37] MIPS: ingenic: initial JZ4780 support
@ 2015-04-21 14:47   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Support the Ingenic JZ4780 SoC using the existing code under
arch/mips/jz4740 now that it has been generalised sufficiently.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase, dropping serial.h & relocating behind CONFIG_MACH_INGENIC.

Changes in v2:
  - None.
---
 arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++++++++++++++++++++
 arch/mips/include/asm/cpu-type.h                   |   2 +-
 .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
 arch/mips/include/asm/mach-jz4740/irq.h            |   4 +
 arch/mips/jz4740/Kconfig                           |   6 ++
 arch/mips/jz4740/Makefile                          |   4 +-
 arch/mips/jz4740/setup.c                           |   3 +
 arch/mips/jz4740/time.c                            |   7 +-
 8 files changed, 124 insertions(+), 6 deletions(-)
 create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi

diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi
new file mode 100644
index 0000000..5e44dd6
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi
@@ -0,0 +1,101 @@
+#include <dt-bindings/clock/jz4780-cgu.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "ingenic,jz4780";
+
+	cpuintc: interrupt-controller {
+		#address-cells = <0>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		compatible = "mti,cpu-interrupt-controller";
+	};
+
+	intc: interrupt-controller@10001000 {
+		compatible = "ingenic,jz4780-intc";
+		reg = <0x10001000 0x50>;
+
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		interrupt-parent = <&cpuintc>;
+		interrupts = <2>;
+	};
+
+	ext: ext {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+	};
+
+	rtc: rtc {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	cgu: jz4780-cgu@10000000 {
+		compatible = "ingenic,jz4780-cgu";
+		reg = <0x10000000 0x100>;
+
+		clocks = <&ext>, <&rtc>;
+		clock-names = "ext", "rtc";
+
+		#clock-cells = <1>;
+	};
+
+	uart0: serial@10030000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10030000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <51>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART0>;
+		clock-names = "baud", "module";
+	};
+
+	uart1: serial@10031000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10031000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <50>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART1>;
+		clock-names = "baud", "module";
+	};
+
+	uart2: serial@10032000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10032000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <49>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART2>;
+		clock-names = "baud", "module";
+	};
+
+	uart3: serial@10033000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10033000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <48>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART3>;
+		clock-names = "baud", "module";
+	};
+
+	uart4: serial@10034000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10034000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <34>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART4>;
+		clock-names = "baud", "module";
+	};
+};
diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index 33f3cab..d41e8e2 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -32,12 +32,12 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	case CPU_4KC:
 	case CPU_ALCHEMY:
 	case CPU_PR4450:
-	case CPU_JZRISC:
 #endif
 
 #if defined(CONFIG_SYS_HAS_CPU_MIPS32_R1) || \
     defined(CONFIG_SYS_HAS_CPU_MIPS32_R2)
 	case CPU_4KEC:
+	case CPU_JZRISC:
 #endif
 
 #ifdef CONFIG_SYS_HAS_CPU_MIPS32_R2
diff --git a/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h
index a225baa..0933f94 100644
--- a/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h
@@ -12,8 +12,6 @@
 #define cpu_has_3k_cache	0
 #define cpu_has_4k_cache	1
 #define cpu_has_tx39_cache	0
-#define cpu_has_fpu		0
-#define cpu_has_32fpr	0
 #define cpu_has_counter		0
 #define cpu_has_watch		1
 #define cpu_has_divec		1
@@ -34,7 +32,6 @@
 #define cpu_has_ic_fills_f_dc	0
 #define cpu_has_pindexed_dcache 0
 #define cpu_has_mips32r1	1
-#define cpu_has_mips32r2	0
 #define cpu_has_mips64r1	0
 #define cpu_has_mips64r2	0
 #define cpu_has_dsp		0
diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
index b218f76..9b439fc 100644
--- a/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -21,6 +21,8 @@
 
 #ifdef CONFIG_MACH_JZ4740
 # define NR_INTC_IRQS	32
+#else
+# define NR_INTC_IRQS	64
 #endif
 
 /* 1st-level interrupts */
@@ -48,6 +50,8 @@
 #define JZ4740_IRQ_IPU		JZ4740_IRQ(29)
 #define JZ4740_IRQ_LCD		JZ4740_IRQ(30)
 
+#define JZ4780_IRQ_TCU2		JZ4740_IRQ(25)
+
 /* 2nd-level interrupts */
 #define JZ4740_IRQ_DMA(x)	(JZ4740_IRQ(NR_INTC_IRQS) + (x))
 
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index dff0966..21adcea 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -12,3 +12,9 @@ endchoice
 config MACH_JZ4740
 	bool
 	select SYS_HAS_CPU_MIPS32_R1
+
+config MACH_JZ4780
+	bool
+	select MIPS_CPU_SCACHE
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_SUPPORTS_HIGHMEM
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 89ce401..39d70bd 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -5,7 +5,9 @@
 # Object file lists.
 
 obj-y += prom.o time.o reset.o setup.o \
-	gpio.o platform.o timer.o
+	platform.o timer.o
+
+obj-$(CONFIG_MACH_JZ4740) += gpio.o
 
 CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
 
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 1bed3cb..510fc0d 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -83,6 +83,9 @@ arch_initcall(populate_machine);
 
 const char *get_system_type(void)
 {
+	if (config_enabled(CONFIG_MACH_JZ4780))
+		return "JZ4780";
+
 	return "JZ4740";
 }
 
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index 9172553..7ab47fe 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -102,7 +102,12 @@ static struct clock_event_device jz4740_clockevent = {
 	.set_next_event = jz4740_clockevent_set_next,
 	.set_mode = jz4740_clockevent_set_mode,
 	.rating = 200,
+#ifdef CONFIG_MACH_JZ4740
 	.irq = JZ4740_IRQ_TCU0,
+#endif
+#ifdef CONFIG_MACH_JZ4780
+	.irq = JZ4780_IRQ_TCU2,
+#endif
 };
 
 static struct irqaction timer_irqaction = {
@@ -144,7 +149,7 @@ void __init plat_time_init(void)
 
 	sched_clock_register(jz4740_read_sched_clock, 16, clk_rate);
 
-	setup_irq(JZ4740_IRQ_TCU0, &timer_irqaction);
+	setup_irq(jz4740_clockevent.irq, &timer_irqaction);
 
 	ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT;
 
-- 
2.3.5

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

* [PATCH v3 36/37] MIPS: ingenic: initial JZ4780 support
@ 2015-04-21 14:47   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Support the Ingenic JZ4780 SoC using the existing code under
arch/mips/jz4740 now that it has been generalised sufficiently.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase, dropping serial.h & relocating behind CONFIG_MACH_INGENIC.

Changes in v2:
  - None.
---
 arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++++++++++++++++++++
 arch/mips/include/asm/cpu-type.h                   |   2 +-
 .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
 arch/mips/include/asm/mach-jz4740/irq.h            |   4 +
 arch/mips/jz4740/Kconfig                           |   6 ++
 arch/mips/jz4740/Makefile                          |   4 +-
 arch/mips/jz4740/setup.c                           |   3 +
 arch/mips/jz4740/time.c                            |   7 +-
 8 files changed, 124 insertions(+), 6 deletions(-)
 create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi

diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi
new file mode 100644
index 0000000..5e44dd6
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi
@@ -0,0 +1,101 @@
+#include <dt-bindings/clock/jz4780-cgu.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "ingenic,jz4780";
+
+	cpuintc: interrupt-controller {
+		#address-cells = <0>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		compatible = "mti,cpu-interrupt-controller";
+	};
+
+	intc: interrupt-controller@10001000 {
+		compatible = "ingenic,jz4780-intc";
+		reg = <0x10001000 0x50>;
+
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		interrupt-parent = <&cpuintc>;
+		interrupts = <2>;
+	};
+
+	ext: ext {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+	};
+
+	rtc: rtc {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	cgu: jz4780-cgu@10000000 {
+		compatible = "ingenic,jz4780-cgu";
+		reg = <0x10000000 0x100>;
+
+		clocks = <&ext>, <&rtc>;
+		clock-names = "ext", "rtc";
+
+		#clock-cells = <1>;
+	};
+
+	uart0: serial@10030000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10030000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <51>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART0>;
+		clock-names = "baud", "module";
+	};
+
+	uart1: serial@10031000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10031000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <50>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART1>;
+		clock-names = "baud", "module";
+	};
+
+	uart2: serial@10032000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10032000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <49>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART2>;
+		clock-names = "baud", "module";
+	};
+
+	uart3: serial@10033000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10033000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <48>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART3>;
+		clock-names = "baud", "module";
+	};
+
+	uart4: serial@10034000 {
+		compatible = "ingenic,jz4780-uart";
+		reg = <0x10034000 0x100>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <34>;
+
+		clocks = <&ext>, <&cgu JZ4780_CLK_UART4>;
+		clock-names = "baud", "module";
+	};
+};
diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index 33f3cab..d41e8e2 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -32,12 +32,12 @@ static inline int __pure __get_cpu_type(const int cpu_type)
 	case CPU_4KC:
 	case CPU_ALCHEMY:
 	case CPU_PR4450:
-	case CPU_JZRISC:
 #endif
 
 #if defined(CONFIG_SYS_HAS_CPU_MIPS32_R1) || \
     defined(CONFIG_SYS_HAS_CPU_MIPS32_R2)
 	case CPU_4KEC:
+	case CPU_JZRISC:
 #endif
 
 #ifdef CONFIG_SYS_HAS_CPU_MIPS32_R2
diff --git a/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h
index a225baa..0933f94 100644
--- a/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h
+++ b/arch/mips/include/asm/mach-jz4740/cpu-feature-overrides.h
@@ -12,8 +12,6 @@
 #define cpu_has_3k_cache	0
 #define cpu_has_4k_cache	1
 #define cpu_has_tx39_cache	0
-#define cpu_has_fpu		0
-#define cpu_has_32fpr	0
 #define cpu_has_counter		0
 #define cpu_has_watch		1
 #define cpu_has_divec		1
@@ -34,7 +32,6 @@
 #define cpu_has_ic_fills_f_dc	0
 #define cpu_has_pindexed_dcache 0
 #define cpu_has_mips32r1	1
-#define cpu_has_mips32r2	0
 #define cpu_has_mips64r1	0
 #define cpu_has_mips64r2	0
 #define cpu_has_dsp		0
diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
index b218f76..9b439fc 100644
--- a/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -21,6 +21,8 @@
 
 #ifdef CONFIG_MACH_JZ4740
 # define NR_INTC_IRQS	32
+#else
+# define NR_INTC_IRQS	64
 #endif
 
 /* 1st-level interrupts */
@@ -48,6 +50,8 @@
 #define JZ4740_IRQ_IPU		JZ4740_IRQ(29)
 #define JZ4740_IRQ_LCD		JZ4740_IRQ(30)
 
+#define JZ4780_IRQ_TCU2		JZ4740_IRQ(25)
+
 /* 2nd-level interrupts */
 #define JZ4740_IRQ_DMA(x)	(JZ4740_IRQ(NR_INTC_IRQS) + (x))
 
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index dff0966..21adcea 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -12,3 +12,9 @@ endchoice
 config MACH_JZ4740
 	bool
 	select SYS_HAS_CPU_MIPS32_R1
+
+config MACH_JZ4780
+	bool
+	select MIPS_CPU_SCACHE
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_SUPPORTS_HIGHMEM
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index 89ce401..39d70bd 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -5,7 +5,9 @@
 # Object file lists.
 
 obj-y += prom.o time.o reset.o setup.o \
-	gpio.o platform.o timer.o
+	platform.o timer.o
+
+obj-$(CONFIG_MACH_JZ4740) += gpio.o
 
 CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
 
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 1bed3cb..510fc0d 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -83,6 +83,9 @@ arch_initcall(populate_machine);
 
 const char *get_system_type(void)
 {
+	if (config_enabled(CONFIG_MACH_JZ4780))
+		return "JZ4780";
+
 	return "JZ4740";
 }
 
diff --git a/arch/mips/jz4740/time.c b/arch/mips/jz4740/time.c
index 9172553..7ab47fe 100644
--- a/arch/mips/jz4740/time.c
+++ b/arch/mips/jz4740/time.c
@@ -102,7 +102,12 @@ static struct clock_event_device jz4740_clockevent = {
 	.set_next_event = jz4740_clockevent_set_next,
 	.set_mode = jz4740_clockevent_set_mode,
 	.rating = 200,
+#ifdef CONFIG_MACH_JZ4740
 	.irq = JZ4740_IRQ_TCU0,
+#endif
+#ifdef CONFIG_MACH_JZ4780
+	.irq = JZ4780_IRQ_TCU2,
+#endif
 };
 
 static struct irqaction timer_irqaction = {
@@ -144,7 +149,7 @@ void __init plat_time_init(void)
 
 	sched_clock_register(jz4740_read_sched_clock, 16, clk_rate);
 
-	setup_irq(JZ4740_IRQ_TCU0, &timer_irqaction);
+	setup_irq(jz4740_clockevent.irq, &timer_irqaction);
 
 	ctrl = JZ_TIMER_CTRL_PRESCALE_16 | JZ_TIMER_CTRL_SRC_EXT;
 
-- 
2.3.5

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

* [PATCH v3 37/37] MIPS: ingenic: initial MIPS Creator CI20 support
@ 2015-04-21 14:47   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Add an initial device tree for the Ingenic JZ4780 based MIPS Creator
CI20 board.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase, relocating behind CONFIG_MACH_INGENIC.

Changes in v2:
  - None.
---
 arch/mips/boot/dts/ingenic/Makefile |   1 +
 arch/mips/boot/dts/ingenic/ci20.dts |  21 +++++
 arch/mips/configs/ci20_defconfig    | 169 ++++++++++++++++++++++++++++++++++++
 arch/mips/jz4740/Kconfig            |   4 +
 4 files changed, 195 insertions(+)
 create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
 create mode 100644 arch/mips/configs/ci20_defconfig

diff --git a/arch/mips/boot/dts/ingenic/Makefile b/arch/mips/boot/dts/ingenic/Makefile
index 0c84f0b..f2b864f 100644
--- a/arch/mips/boot/dts/ingenic/Makefile
+++ b/arch/mips/boot/dts/ingenic/Makefile
@@ -1,4 +1,5 @@
 dtb-$(CONFIG_JZ4740_QI_LB60)	+= qi_lb60.dtb
+dtb-$(CONFIG_JZ4780_CI20)	+= ci20.dtb
 
 obj-y				+= $(patsubst %.dtb, %.dtb.o, $(dtb-y))
 
diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts
new file mode 100644
index 0000000..4f882ef
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/ci20.dts
@@ -0,0 +1,21 @@
+/dts-v1/;
+
+#include "jz4780.dtsi"
+
+/ {
+	compatible = "img,ci20", "ingenic,jz4780";
+
+	chosen {
+		stdout-path = &uart4;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x10000000
+		       0x30000000 0x30000000>;
+	};
+};
+
+&ext {
+	clock-frequency = <48000000>;
+};
diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig
new file mode 100644
index 0000000..0305fe0
--- /dev/null
+++ b/arch/mips/configs/ci20_defconfig
@@ -0,0 +1,169 @@
+CONFIG_MACH_INGENIC=y
+CONFIG_JZ4780_CI20=y
+CONFIG_HIGHMEM=y
+# CONFIG_COMPACTION is not set
+CONFIG_CMA=y
+CONFIG_HZ_100=y
+CONFIG_PREEMPT=y
+# CONFIG_SECCOMP is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="arch/mips/boot/ramdisk.cpio.xz"
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=2
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=5
+CONFIG_SERIAL_8250_RUNTIME_UARTS=5
+CONFIG_SERIAL_8250_INGENIC=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_JZ4780=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DEBUG=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_MEMORY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_PROC_KCORE=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_KOI8_U=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_TIMEOUT=10
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_STACKTRACE=y
+# CONFIG_FTRACE is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="earlycon console=ttyS4,115200 clk_ignore_unused nowait"
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 21adcea..36f8201 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -7,6 +7,10 @@ config JZ4740_QI_LB60
 	bool "Qi Hardware Ben NanoNote"
 	select MACH_JZ4740
 
+config JZ4780_CI20
+	bool "MIPS Creator CI20"
+	select MACH_JZ4780
+
 endchoice
 
 config MACH_JZ4740
-- 
2.3.5

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

* [PATCH v3 37/37] MIPS: ingenic: initial MIPS Creator CI20 support
@ 2015-04-21 14:47   ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:47 UTC (permalink / raw)
  To: linux-mips; +Cc: Paul Burton, Lars-Peter Clausen

Add an initial device tree for the Ingenic JZ4780 based MIPS Creator
CI20 board.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
---
Changes in v3:
  - Rebase, relocating behind CONFIG_MACH_INGENIC.

Changes in v2:
  - None.
---
 arch/mips/boot/dts/ingenic/Makefile |   1 +
 arch/mips/boot/dts/ingenic/ci20.dts |  21 +++++
 arch/mips/configs/ci20_defconfig    | 169 ++++++++++++++++++++++++++++++++++++
 arch/mips/jz4740/Kconfig            |   4 +
 4 files changed, 195 insertions(+)
 create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
 create mode 100644 arch/mips/configs/ci20_defconfig

diff --git a/arch/mips/boot/dts/ingenic/Makefile b/arch/mips/boot/dts/ingenic/Makefile
index 0c84f0b..f2b864f 100644
--- a/arch/mips/boot/dts/ingenic/Makefile
+++ b/arch/mips/boot/dts/ingenic/Makefile
@@ -1,4 +1,5 @@
 dtb-$(CONFIG_JZ4740_QI_LB60)	+= qi_lb60.dtb
+dtb-$(CONFIG_JZ4780_CI20)	+= ci20.dtb
 
 obj-y				+= $(patsubst %.dtb, %.dtb.o, $(dtb-y))
 
diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts
new file mode 100644
index 0000000..4f882ef
--- /dev/null
+++ b/arch/mips/boot/dts/ingenic/ci20.dts
@@ -0,0 +1,21 @@
+/dts-v1/;
+
+#include "jz4780.dtsi"
+
+/ {
+	compatible = "img,ci20", "ingenic,jz4780";
+
+	chosen {
+		stdout-path = &uart4;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x10000000
+		       0x30000000 0x30000000>;
+	};
+};
+
+&ext {
+	clock-frequency = <48000000>;
+};
diff --git a/arch/mips/configs/ci20_defconfig b/arch/mips/configs/ci20_defconfig
new file mode 100644
index 0000000..0305fe0
--- /dev/null
+++ b/arch/mips/configs/ci20_defconfig
@@ -0,0 +1,169 @@
+CONFIG_MACH_INGENIC=y
+CONFIG_JZ4780_CI20=y
+CONFIG_HIGHMEM=y
+# CONFIG_COMPACTION is not set
+CONFIG_CMA=y
+CONFIG_HZ_100=y
+CONFIG_PREEMPT=y
+# CONFIG_SECCOMP is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="arch/mips/boot/ramdisk.cpio.xz"
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=2
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=5
+CONFIG_SERIAL_8250_RUNTIME_UARTS=5
+CONFIG_SERIAL_8250_INGENIC=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_JZ4780=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DEBUG=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_MEMORY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_PROC_KCORE=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_KOI8_U=y
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_TIMEOUT=10
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_STACKTRACE=y
+# CONFIG_FTRACE is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="earlycon console=ttyS4,115200 clk_ignore_unused nowait"
diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
index 21adcea..36f8201 100644
--- a/arch/mips/jz4740/Kconfig
+++ b/arch/mips/jz4740/Kconfig
@@ -7,6 +7,10 @@ config JZ4740_QI_LB60
 	bool "Qi Hardware Ben NanoNote"
 	select MACH_JZ4740
 
+config JZ4780_CI20
+	bool "MIPS Creator CI20"
+	select MACH_JZ4780
+
 endchoice
 
 config MACH_JZ4740
-- 
2.3.5

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

* Re: [PATCH v3 00/37] JZ4780 & CI20 support
  2015-04-21 14:46 ` Paul Burton
  (?)
@ 2015-04-21 14:54     ` Paul Burton
  -1 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:54 UTC (permalink / raw)
  To: linux-mips-6z/3iImG2C8G8FEW9MqTrA
  Cc: Lars-Peter Clausen, Paul Cercueil, Thomas Gleixner, Jason Cooper,
	Mike Turquette, Greg Kroah-Hartman,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA

On Tue, Apr 21, 2015 at 03:46:27PM +0100, Paul Burton wrote:
> This series introduces initial support for the Ingenic JZ4780 SoC and
> the Imagination Technologies MIPS Creator CI20 board which is built
> around it. In the process the existing JZ4740 & qi_lb60 code gains
> initial support for using DeviceTree such that much of the existing
> platform code under arch/mips/jz4740 can be shared.
> 
> The series has undergone quite a bit of restructure since v2. Each
> patch contains a changelog indicating its differences, but a rough
> overview for changes across the series would be:
> 
>   - s/jz47xx/ingenic/ in various places, to reflect the fact that
>     Ingenic have changed the naming scheme for their newest SoCs
>     (now Mxxx).
> 
>   - Restructure the Kconfig entries to provide a MACH_INGENIC
>     indicating and Ingenic SoC, and have boards select the
>     appropriate SoC symbol.
> 
>   - Merge DT binding documentation where SoC bindings differ only
>     by compatible strings.
> 
>   - Capitalise "JZ" in SoC names, where not identifiers in code,
>     to match the way Ingenic write them.
> 
>   - Further clean up the Ingenic SoC interrupt controller driver
>     and move it under drivers/irqchip/.
> 
> Review appreciated, and hopefully this can make it into v4.2.

(Of course I forgot something... This applies atop next-20150421 :) )

Thanks,
    Paul

> Thanks,
>     Paul
> 
> Paul Burton (37):
>   devicetree/bindings: add Ingenic Semiconductor vendor prefix
>   devicetree/bindings: add Qi Hardware vendor prefix
>   MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
>   MIPS: ingenic: add newer vendor IDs
>   MIPS: JZ4740: require & include DT
>   MIPS: irq_cpu: declare irqchip table entry
>   MIPS: JZ4740: probe CPU interrupt controller via DT
>   MIPS: JZ4740: use generic plat_irq_dispatch
>   MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
>   devicetree: document Ingenic SoC interrupt controller binding
>   MIPS: JZ4740: probe interrupt controller via DT
>   MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
>   MIPS: JZ4740: register an irq_domain for the interrupt controller
>   MIPS: JZ4740: drop intc debugfs code
>   MIPS: JZ4740: remove jz_intc_base global
>   MIPS: JZ4740: support >32 interrupts
>   MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
>   MIPS: JZ4740: read intc base address from DT
>   MIPS: JZ4740: avoid JZ4740-specific naming
>   MIPS: JZ4740: support newer SoC interrupt controllers
>   irqchip: move Ingenic SoC intc driver to drivers/irqchip
>   MIPS: JZ4740: call jz4740_clock_init earlier
>   MIPS: JZ4740: replace use of jz4740_clock_bdata
>   devicetree: add Ingenic CGU binding documentation
>   clk: ingenic: add driver for Ingenic SoC CGU clocks
>   MIPS,clk: migrate JZ4740 to common clock framework
>   MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
>   MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
>   MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
>   clk: ingenic: add JZ4780 CGU support
>   MIPS: JZ4740: remove clock.h
>   MIPS: JZ4740: only detect RAM size if not specified in DT
>   devicetree: document Ingenic SoC UART binding
>   serial: 8250_ingenic: support for Ingenic SoC UARTs
>   MIPS: JZ4740: use Ingenic SoC UART driver
>   MIPS: ingenic: initial JZ4780 support
>   MIPS: ingenic: initial MIPS Creator CI20 support
> 
>  .../devicetree/bindings/clock/ingenic,cgu.txt      |  53 ++
>  .../bindings/interrupt-controller/ingenic,intc.txt |  25 +
>  .../devicetree/bindings/serial/ingenic,uart.txt    |  22 +
>  .../devicetree/bindings/vendor-prefixes.txt        |   2 +
>  arch/mips/Kconfig                                  |  11 +-
>  arch/mips/boot/dts/Makefile                        |   1 +
>  arch/mips/boot/dts/ingenic/Makefile                |  10 +
>  arch/mips/boot/dts/ingenic/ci20.dts                |  21 +
>  arch/mips/boot/dts/ingenic/jz4740.dtsi             |  68 ++
>  arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++
>  arch/mips/boot/dts/ingenic/qi_lb60.dts             |  15 +
>  arch/mips/configs/ci20_defconfig                   | 169 ++++
>  arch/mips/configs/qi_lb60_defconfig                |   3 +-
>  arch/mips/include/asm/cpu-type.h                   |   2 +-
>  arch/mips/include/asm/cpu.h                        |   6 +-
>  arch/mips/include/asm/mach-jz4740/clock.h          |   3 +
>  .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
>  arch/mips/include/asm/mach-jz4740/irq.h            |  14 +-
>  arch/mips/include/asm/mach-jz4740/platform.h       |   2 -
>  arch/mips/jz4740/Kconfig                           |  17 +-
>  arch/mips/jz4740/Makefile                          |   8 +-
>  arch/mips/jz4740/Platform                          |   8 +-
>  arch/mips/jz4740/board-qi_lb60.c                   |   7 -
>  arch/mips/jz4740/clock-debugfs.c                   | 108 ---
>  arch/mips/jz4740/clock.c                           | 924 ---------------------
>  arch/mips/jz4740/clock.h                           |  76 --
>  arch/mips/jz4740/gpio.c                            |   7 +-
>  arch/mips/jz4740/irq.c                             | 162 ----
>  arch/mips/jz4740/platform.c                        |  38 +-
>  arch/mips/jz4740/pm.c                              |   2 -
>  arch/mips/jz4740/prom.c                            |  13 -
>  arch/mips/jz4740/reset.c                           |  13 +-
>  arch/mips/jz4740/serial.c                          |  33 -
>  arch/mips/jz4740/serial.h                          |  23 -
>  arch/mips/jz4740/setup.c                           |  36 +-
>  arch/mips/jz4740/time.c                            |  19 +-
>  arch/mips/kernel/cpu-probe.c                       |   4 +-
>  arch/mips/kernel/irq_cpu.c                         |   3 +
>  drivers/clk/Makefile                               |   1 +
>  drivers/clk/ingenic/Makefile                       |   3 +
>  drivers/clk/ingenic/cgu.c                          | 711 ++++++++++++++++
>  drivers/clk/ingenic/cgu.h                          | 223 +++++
>  drivers/clk/ingenic/jz4740-cgu.c                   | 301 +++++++
>  drivers/clk/ingenic/jz4780-cgu.c                   | 732 ++++++++++++++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-ingenic.c                      | 171 ++++
>  drivers/tty/serial/8250/8250_ingenic.c             | 261 ++++++
>  drivers/tty/serial/8250/Kconfig                    |   9 +
>  drivers/tty/serial/8250/Makefile                   |   3 +
>  include/dt-bindings/clock/jz4740-cgu.h             |  37 +
>  include/dt-bindings/clock/jz4780-cgu.h             |  88 ++
>  .../irq.h => include/linux/irqchip/ingenic.h       |   8 +-
>  53 files changed, 3162 insertions(+), 1424 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
>  create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
>  create mode 100644 arch/mips/boot/dts/ingenic/Makefile
>  create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts
>  create mode 100644 arch/mips/configs/ci20_defconfig
>  delete mode 100644 arch/mips/jz4740/clock-debugfs.c
>  delete mode 100644 arch/mips/jz4740/clock.c
>  delete mode 100644 arch/mips/jz4740/clock.h
>  delete mode 100644 arch/mips/jz4740/irq.c
>  delete mode 100644 arch/mips/jz4740/serial.c
>  delete mode 100644 arch/mips/jz4740/serial.h
>  create mode 100644 drivers/clk/ingenic/Makefile
>  create mode 100644 drivers/clk/ingenic/cgu.c
>  create mode 100644 drivers/clk/ingenic/cgu.h
>  create mode 100644 drivers/clk/ingenic/jz4740-cgu.c
>  create mode 100644 drivers/clk/ingenic/jz4780-cgu.c
>  create mode 100644 drivers/irqchip/irq-ingenic.c
>  create mode 100644 drivers/tty/serial/8250/8250_ingenic.c
>  create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
>  create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
>  rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (74%)
> 
> -- 
> 2.3.5
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v3 00/37] JZ4780 & CI20 support
@ 2015-04-21 14:54     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:54 UTC (permalink / raw)
  To: linux-mips
  Cc: Lars-Peter Clausen, Paul Cercueil, Thomas Gleixner, Jason Cooper,
	Mike Turquette, Greg Kroah-Hartman, devicetree, linux-serial

On Tue, Apr 21, 2015 at 03:46:27PM +0100, Paul Burton wrote:
> This series introduces initial support for the Ingenic JZ4780 SoC and
> the Imagination Technologies MIPS Creator CI20 board which is built
> around it. In the process the existing JZ4740 & qi_lb60 code gains
> initial support for using DeviceTree such that much of the existing
> platform code under arch/mips/jz4740 can be shared.
> 
> The series has undergone quite a bit of restructure since v2. Each
> patch contains a changelog indicating its differences, but a rough
> overview for changes across the series would be:
> 
>   - s/jz47xx/ingenic/ in various places, to reflect the fact that
>     Ingenic have changed the naming scheme for their newest SoCs
>     (now Mxxx).
> 
>   - Restructure the Kconfig entries to provide a MACH_INGENIC
>     indicating and Ingenic SoC, and have boards select the
>     appropriate SoC symbol.
> 
>   - Merge DT binding documentation where SoC bindings differ only
>     by compatible strings.
> 
>   - Capitalise "JZ" in SoC names, where not identifiers in code,
>     to match the way Ingenic write them.
> 
>   - Further clean up the Ingenic SoC interrupt controller driver
>     and move it under drivers/irqchip/.
> 
> Review appreciated, and hopefully this can make it into v4.2.

(Of course I forgot something... This applies atop next-20150421 :) )

Thanks,
    Paul

> Thanks,
>     Paul
> 
> Paul Burton (37):
>   devicetree/bindings: add Ingenic Semiconductor vendor prefix
>   devicetree/bindings: add Qi Hardware vendor prefix
>   MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
>   MIPS: ingenic: add newer vendor IDs
>   MIPS: JZ4740: require & include DT
>   MIPS: irq_cpu: declare irqchip table entry
>   MIPS: JZ4740: probe CPU interrupt controller via DT
>   MIPS: JZ4740: use generic plat_irq_dispatch
>   MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
>   devicetree: document Ingenic SoC interrupt controller binding
>   MIPS: JZ4740: probe interrupt controller via DT
>   MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
>   MIPS: JZ4740: register an irq_domain for the interrupt controller
>   MIPS: JZ4740: drop intc debugfs code
>   MIPS: JZ4740: remove jz_intc_base global
>   MIPS: JZ4740: support >32 interrupts
>   MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
>   MIPS: JZ4740: read intc base address from DT
>   MIPS: JZ4740: avoid JZ4740-specific naming
>   MIPS: JZ4740: support newer SoC interrupt controllers
>   irqchip: move Ingenic SoC intc driver to drivers/irqchip
>   MIPS: JZ4740: call jz4740_clock_init earlier
>   MIPS: JZ4740: replace use of jz4740_clock_bdata
>   devicetree: add Ingenic CGU binding documentation
>   clk: ingenic: add driver for Ingenic SoC CGU clocks
>   MIPS,clk: migrate JZ4740 to common clock framework
>   MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
>   MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
>   MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
>   clk: ingenic: add JZ4780 CGU support
>   MIPS: JZ4740: remove clock.h
>   MIPS: JZ4740: only detect RAM size if not specified in DT
>   devicetree: document Ingenic SoC UART binding
>   serial: 8250_ingenic: support for Ingenic SoC UARTs
>   MIPS: JZ4740: use Ingenic SoC UART driver
>   MIPS: ingenic: initial JZ4780 support
>   MIPS: ingenic: initial MIPS Creator CI20 support
> 
>  .../devicetree/bindings/clock/ingenic,cgu.txt      |  53 ++
>  .../bindings/interrupt-controller/ingenic,intc.txt |  25 +
>  .../devicetree/bindings/serial/ingenic,uart.txt    |  22 +
>  .../devicetree/bindings/vendor-prefixes.txt        |   2 +
>  arch/mips/Kconfig                                  |  11 +-
>  arch/mips/boot/dts/Makefile                        |   1 +
>  arch/mips/boot/dts/ingenic/Makefile                |  10 +
>  arch/mips/boot/dts/ingenic/ci20.dts                |  21 +
>  arch/mips/boot/dts/ingenic/jz4740.dtsi             |  68 ++
>  arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++
>  arch/mips/boot/dts/ingenic/qi_lb60.dts             |  15 +
>  arch/mips/configs/ci20_defconfig                   | 169 ++++
>  arch/mips/configs/qi_lb60_defconfig                |   3 +-
>  arch/mips/include/asm/cpu-type.h                   |   2 +-
>  arch/mips/include/asm/cpu.h                        |   6 +-
>  arch/mips/include/asm/mach-jz4740/clock.h          |   3 +
>  .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
>  arch/mips/include/asm/mach-jz4740/irq.h            |  14 +-
>  arch/mips/include/asm/mach-jz4740/platform.h       |   2 -
>  arch/mips/jz4740/Kconfig                           |  17 +-
>  arch/mips/jz4740/Makefile                          |   8 +-
>  arch/mips/jz4740/Platform                          |   8 +-
>  arch/mips/jz4740/board-qi_lb60.c                   |   7 -
>  arch/mips/jz4740/clock-debugfs.c                   | 108 ---
>  arch/mips/jz4740/clock.c                           | 924 ---------------------
>  arch/mips/jz4740/clock.h                           |  76 --
>  arch/mips/jz4740/gpio.c                            |   7 +-
>  arch/mips/jz4740/irq.c                             | 162 ----
>  arch/mips/jz4740/platform.c                        |  38 +-
>  arch/mips/jz4740/pm.c                              |   2 -
>  arch/mips/jz4740/prom.c                            |  13 -
>  arch/mips/jz4740/reset.c                           |  13 +-
>  arch/mips/jz4740/serial.c                          |  33 -
>  arch/mips/jz4740/serial.h                          |  23 -
>  arch/mips/jz4740/setup.c                           |  36 +-
>  arch/mips/jz4740/time.c                            |  19 +-
>  arch/mips/kernel/cpu-probe.c                       |   4 +-
>  arch/mips/kernel/irq_cpu.c                         |   3 +
>  drivers/clk/Makefile                               |   1 +
>  drivers/clk/ingenic/Makefile                       |   3 +
>  drivers/clk/ingenic/cgu.c                          | 711 ++++++++++++++++
>  drivers/clk/ingenic/cgu.h                          | 223 +++++
>  drivers/clk/ingenic/jz4740-cgu.c                   | 301 +++++++
>  drivers/clk/ingenic/jz4780-cgu.c                   | 732 ++++++++++++++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-ingenic.c                      | 171 ++++
>  drivers/tty/serial/8250/8250_ingenic.c             | 261 ++++++
>  drivers/tty/serial/8250/Kconfig                    |   9 +
>  drivers/tty/serial/8250/Makefile                   |   3 +
>  include/dt-bindings/clock/jz4740-cgu.h             |  37 +
>  include/dt-bindings/clock/jz4780-cgu.h             |  88 ++
>  .../irq.h => include/linux/irqchip/ingenic.h       |   8 +-
>  53 files changed, 3162 insertions(+), 1424 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
>  create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
>  create mode 100644 arch/mips/boot/dts/ingenic/Makefile
>  create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts
>  create mode 100644 arch/mips/configs/ci20_defconfig
>  delete mode 100644 arch/mips/jz4740/clock-debugfs.c
>  delete mode 100644 arch/mips/jz4740/clock.c
>  delete mode 100644 arch/mips/jz4740/clock.h
>  delete mode 100644 arch/mips/jz4740/irq.c
>  delete mode 100644 arch/mips/jz4740/serial.c
>  delete mode 100644 arch/mips/jz4740/serial.h
>  create mode 100644 drivers/clk/ingenic/Makefile
>  create mode 100644 drivers/clk/ingenic/cgu.c
>  create mode 100644 drivers/clk/ingenic/cgu.h
>  create mode 100644 drivers/clk/ingenic/jz4740-cgu.c
>  create mode 100644 drivers/clk/ingenic/jz4780-cgu.c
>  create mode 100644 drivers/irqchip/irq-ingenic.c
>  create mode 100644 drivers/tty/serial/8250/8250_ingenic.c
>  create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
>  create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
>  rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (74%)
> 
> -- 
> 2.3.5
> 

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

* Re: [PATCH v3 00/37] JZ4780 & CI20 support
@ 2015-04-21 14:54     ` Paul Burton
  0 siblings, 0 replies; 102+ messages in thread
From: Paul Burton @ 2015-04-21 14:54 UTC (permalink / raw)
  To: linux-mips
  Cc: Lars-Peter Clausen, Paul Cercueil, Thomas Gleixner, Jason Cooper,
	Mike Turquette, Greg Kroah-Hartman, devicetree, linux-serial

On Tue, Apr 21, 2015 at 03:46:27PM +0100, Paul Burton wrote:
> This series introduces initial support for the Ingenic JZ4780 SoC and
> the Imagination Technologies MIPS Creator CI20 board which is built
> around it. In the process the existing JZ4740 & qi_lb60 code gains
> initial support for using DeviceTree such that much of the existing
> platform code under arch/mips/jz4740 can be shared.
> 
> The series has undergone quite a bit of restructure since v2. Each
> patch contains a changelog indicating its differences, but a rough
> overview for changes across the series would be:
> 
>   - s/jz47xx/ingenic/ in various places, to reflect the fact that
>     Ingenic have changed the naming scheme for their newest SoCs
>     (now Mxxx).
> 
>   - Restructure the Kconfig entries to provide a MACH_INGENIC
>     indicating and Ingenic SoC, and have boards select the
>     appropriate SoC symbol.
> 
>   - Merge DT binding documentation where SoC bindings differ only
>     by compatible strings.
> 
>   - Capitalise "JZ" in SoC names, where not identifiers in code,
>     to match the way Ingenic write them.
> 
>   - Further clean up the Ingenic SoC interrupt controller driver
>     and move it under drivers/irqchip/.
> 
> Review appreciated, and hopefully this can make it into v4.2.

(Of course I forgot something... This applies atop next-20150421 :) )

Thanks,
    Paul

> Thanks,
>     Paul
> 
> Paul Burton (37):
>   devicetree/bindings: add Ingenic Semiconductor vendor prefix
>   devicetree/bindings: add Qi Hardware vendor prefix
>   MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
>   MIPS: ingenic: add newer vendor IDs
>   MIPS: JZ4740: require & include DT
>   MIPS: irq_cpu: declare irqchip table entry
>   MIPS: JZ4740: probe CPU interrupt controller via DT
>   MIPS: JZ4740: use generic plat_irq_dispatch
>   MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
>   devicetree: document Ingenic SoC interrupt controller binding
>   MIPS: JZ4740: probe interrupt controller via DT
>   MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
>   MIPS: JZ4740: register an irq_domain for the interrupt controller
>   MIPS: JZ4740: drop intc debugfs code
>   MIPS: JZ4740: remove jz_intc_base global
>   MIPS: JZ4740: support >32 interrupts
>   MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
>   MIPS: JZ4740: read intc base address from DT
>   MIPS: JZ4740: avoid JZ4740-specific naming
>   MIPS: JZ4740: support newer SoC interrupt controllers
>   irqchip: move Ingenic SoC intc driver to drivers/irqchip
>   MIPS: JZ4740: call jz4740_clock_init earlier
>   MIPS: JZ4740: replace use of jz4740_clock_bdata
>   devicetree: add Ingenic CGU binding documentation
>   clk: ingenic: add driver for Ingenic SoC CGU clocks
>   MIPS,clk: migrate JZ4740 to common clock framework
>   MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
>   MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
>   MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
>   clk: ingenic: add JZ4780 CGU support
>   MIPS: JZ4740: remove clock.h
>   MIPS: JZ4740: only detect RAM size if not specified in DT
>   devicetree: document Ingenic SoC UART binding
>   serial: 8250_ingenic: support for Ingenic SoC UARTs
>   MIPS: JZ4740: use Ingenic SoC UART driver
>   MIPS: ingenic: initial JZ4780 support
>   MIPS: ingenic: initial MIPS Creator CI20 support
> 
>  .../devicetree/bindings/clock/ingenic,cgu.txt      |  53 ++
>  .../bindings/interrupt-controller/ingenic,intc.txt |  25 +
>  .../devicetree/bindings/serial/ingenic,uart.txt    |  22 +
>  .../devicetree/bindings/vendor-prefixes.txt        |   2 +
>  arch/mips/Kconfig                                  |  11 +-
>  arch/mips/boot/dts/Makefile                        |   1 +
>  arch/mips/boot/dts/ingenic/Makefile                |  10 +
>  arch/mips/boot/dts/ingenic/ci20.dts                |  21 +
>  arch/mips/boot/dts/ingenic/jz4740.dtsi             |  68 ++
>  arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++
>  arch/mips/boot/dts/ingenic/qi_lb60.dts             |  15 +
>  arch/mips/configs/ci20_defconfig                   | 169 ++++
>  arch/mips/configs/qi_lb60_defconfig                |   3 +-
>  arch/mips/include/asm/cpu-type.h                   |   2 +-
>  arch/mips/include/asm/cpu.h                        |   6 +-
>  arch/mips/include/asm/mach-jz4740/clock.h          |   3 +
>  .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
>  arch/mips/include/asm/mach-jz4740/irq.h            |  14 +-
>  arch/mips/include/asm/mach-jz4740/platform.h       |   2 -
>  arch/mips/jz4740/Kconfig                           |  17 +-
>  arch/mips/jz4740/Makefile                          |   8 +-
>  arch/mips/jz4740/Platform                          |   8 +-
>  arch/mips/jz4740/board-qi_lb60.c                   |   7 -
>  arch/mips/jz4740/clock-debugfs.c                   | 108 ---
>  arch/mips/jz4740/clock.c                           | 924 ---------------------
>  arch/mips/jz4740/clock.h                           |  76 --
>  arch/mips/jz4740/gpio.c                            |   7 +-
>  arch/mips/jz4740/irq.c                             | 162 ----
>  arch/mips/jz4740/platform.c                        |  38 +-
>  arch/mips/jz4740/pm.c                              |   2 -
>  arch/mips/jz4740/prom.c                            |  13 -
>  arch/mips/jz4740/reset.c                           |  13 +-
>  arch/mips/jz4740/serial.c                          |  33 -
>  arch/mips/jz4740/serial.h                          |  23 -
>  arch/mips/jz4740/setup.c                           |  36 +-
>  arch/mips/jz4740/time.c                            |  19 +-
>  arch/mips/kernel/cpu-probe.c                       |   4 +-
>  arch/mips/kernel/irq_cpu.c                         |   3 +
>  drivers/clk/Makefile                               |   1 +
>  drivers/clk/ingenic/Makefile                       |   3 +
>  drivers/clk/ingenic/cgu.c                          | 711 ++++++++++++++++
>  drivers/clk/ingenic/cgu.h                          | 223 +++++
>  drivers/clk/ingenic/jz4740-cgu.c                   | 301 +++++++
>  drivers/clk/ingenic/jz4780-cgu.c                   | 732 ++++++++++++++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-ingenic.c                      | 171 ++++
>  drivers/tty/serial/8250/8250_ingenic.c             | 261 ++++++
>  drivers/tty/serial/8250/Kconfig                    |   9 +
>  drivers/tty/serial/8250/Makefile                   |   3 +
>  include/dt-bindings/clock/jz4740-cgu.h             |  37 +
>  include/dt-bindings/clock/jz4780-cgu.h             |  88 ++
>  .../irq.h => include/linux/irqchip/ingenic.h       |   8 +-
>  53 files changed, 3162 insertions(+), 1424 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
>  create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
>  create mode 100644 arch/mips/boot/dts/ingenic/Makefile
>  create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts
>  create mode 100644 arch/mips/configs/ci20_defconfig
>  delete mode 100644 arch/mips/jz4740/clock-debugfs.c
>  delete mode 100644 arch/mips/jz4740/clock.c
>  delete mode 100644 arch/mips/jz4740/clock.h
>  delete mode 100644 arch/mips/jz4740/irq.c
>  delete mode 100644 arch/mips/jz4740/serial.c
>  delete mode 100644 arch/mips/jz4740/serial.h
>  create mode 100644 drivers/clk/ingenic/Makefile
>  create mode 100644 drivers/clk/ingenic/cgu.c
>  create mode 100644 drivers/clk/ingenic/cgu.h
>  create mode 100644 drivers/clk/ingenic/jz4740-cgu.c
>  create mode 100644 drivers/clk/ingenic/jz4780-cgu.c
>  create mode 100644 drivers/irqchip/irq-ingenic.c
>  create mode 100644 drivers/tty/serial/8250/8250_ingenic.c
>  create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
>  create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
>  rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (74%)
> 
> -- 
> 2.3.5
> 

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

* Re: [PATCH v3 10/37] devicetree: document Ingenic SoC interrupt controller binding
  2015-04-21 14:46     ` Paul Burton
@ 2015-04-21 16:56         ` Sergei Shtylyov
  -1 siblings, 0 replies; 102+ messages in thread
From: Sergei Shtylyov @ 2015-04-21 16:56 UTC (permalink / raw)
  To: Paul Burton, linux-mips-6z/3iImG2C8G8FEW9MqTrA
  Cc: Lars-Peter Clausen, devicetree-u79uwXL29TY76Z2rM5mHXA

Hello.

On 04/21/2015 05:46 PM, Paul Burton wrote:

> Add binding documentation for Ingenic SoC interrupt controllers.

> Signed-off-by: Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
> Cc: Lars-Peter Clausen <lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> ---
> Changes in v3:
>    - Merge documentation for various Ingenic SoCs, which only differ by
>      their compatible strings.

> Changes in v2:
>    - None.
> ---
>   .../bindings/interrupt-controller/ingenic,intc.txt | 25 ++++++++++++++++++++++
>   1 file changed, 25 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt

> diff --git a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
> new file mode 100644
> index 0000000..5d652e4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
> @@ -0,0 +1,25 @@
> +Ingenic SoC Interrupt Controller
> +
> +Required properties:
> +
> +- compatible : should be "ingenic,<socname>-intc". For example
> +  "ingenic,jz4740-intc" or "ingenic,jz4780-intc".
> +- reg : Specifies base physical address and size of the registers.
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source. The value shall be 1.
> +- interrupt-parent : phandle of the CPU interrupt controller.
> +- interrupts : Specifies the CPU interrupt the controller is connected to.
> +
> +Example:
> +
> +intc: intc@10001000 {

    The node should be named "interrupt-controller@10001000", according to the 
epAPR standard.

WBR, Sergei

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v3 10/37] devicetree: document Ingenic SoC interrupt controller binding
@ 2015-04-21 16:56         ` Sergei Shtylyov
  0 siblings, 0 replies; 102+ messages in thread
From: Sergei Shtylyov @ 2015-04-21 16:56 UTC (permalink / raw)
  To: Paul Burton, linux-mips; +Cc: Lars-Peter Clausen, devicetree

Hello.

On 04/21/2015 05:46 PM, Paul Burton wrote:

> Add binding documentation for Ingenic SoC interrupt controllers.

> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Cc: devicetree@vger.kernel.org
> ---
> Changes in v3:
>    - Merge documentation for various Ingenic SoCs, which only differ by
>      their compatible strings.

> Changes in v2:
>    - None.
> ---
>   .../bindings/interrupt-controller/ingenic,intc.txt | 25 ++++++++++++++++++++++
>   1 file changed, 25 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt

> diff --git a/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
> new file mode 100644
> index 0000000..5d652e4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
> @@ -0,0 +1,25 @@
> +Ingenic SoC Interrupt Controller
> +
> +Required properties:
> +
> +- compatible : should be "ingenic,<socname>-intc". For example
> +  "ingenic,jz4740-intc" or "ingenic,jz4780-intc".
> +- reg : Specifies base physical address and size of the registers.
> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells : Specifies the number of cells needed to encode an
> +  interrupt source. The value shall be 1.
> +- interrupt-parent : phandle of the CPU interrupt controller.
> +- interrupts : Specifies the CPU interrupt the controller is connected to.
> +
> +Example:
> +
> +intc: intc@10001000 {

    The node should be named "interrupt-controller@10001000", according to the 
epAPR standard.

WBR, Sergei

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

* Re: [PATCH v3 15/37] MIPS: JZ4740: remove jz_intc_base global
@ 2015-04-21 21:09     ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-21 21:09 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

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

Hi Paul,

On Tue, Apr 21, 2015 at 03:46:42PM +0100, Paul Burton wrote:
> Avoid the need for the global variable jz_intc_base by introducing a
> struct ingenic_intc_data and passing it around as the IRQ handler data.
> 
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Jason Cooper <jason@lakedaemon.net>
> ---
> Changes in v3:
>   - New patch.
> ---
>  arch/mips/jz4740/irq.c | 35 ++++++++++++++++++++++++++---------
>  1 file changed, 26 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
> index 615eaa8..498ff28 100644
> --- a/arch/mips/jz4740/irq.c
> +++ b/arch/mips/jz4740/irq.c
> @@ -32,7 +32,9 @@
>  
>  #include "../../drivers/irqchip/irqchip.h"
>  
> -static void __iomem *jz_intc_base;
> +struct ingenic_intc_data {
> +	void __iomem *base;
> +};
>  
>  #define JZ_REG_INTC_STATUS	0x00
>  #define JZ_REG_INTC_MASK	0x04
> @@ -42,9 +44,10 @@ static void __iomem *jz_intc_base;
>  
>  static irqreturn_t jz4740_cascade(int irq, void *data)
>  {
> +	struct ingenic_intc_data *intc = irq_get_handler_data(irq);
>  	uint32_t irq_reg;
>  
> -	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
> +	irq_reg = readl(intc->base + JZ_REG_INTC_PENDING);
>  
>  	if (irq_reg)
>  		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
> @@ -80,21 +83,30 @@ static struct irqaction jz4740_cascade_action = {
>  static int __init jz4740_intc_of_init(struct device_node *node,
>  	struct device_node *parent)
>  {
> +	struct ingenic_intc_data *intc;
>  	struct irq_chip_generic *gc;
>  	struct irq_chip_type *ct;
>  	struct irq_domain *domain;
> -	int parent_irq;
> +	int parent_irq, err = 0;
> +
> +	intc = kzalloc(sizeof(*intc), GFP_KERNEL);
> +	if (!intc) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
>  
>  	parent_irq = irq_of_parse_and_map(node, 0);
> -	if (!parent_irq)
> -		return -EINVAL;
> +	if (!parent_irq) {
> +		err = -EINVAL;
> +		goto out;
> +	}
>  
> -	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
> +	intc->base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
>  
>  	/* Mask all irqs */
> -	writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
> +	writel(0xffffffff, intc->base + JZ_REG_INTC_SET_MASK);
>  
> -	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base,
> +	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, intc->base,
>  		handle_level_irq);
>  
>  	gc->wake_enabled = IRQ_MSK(32);
> @@ -116,7 +128,12 @@ static int __init jz4740_intc_of_init(struct device_node *node,
>  	if (!domain)
>  		pr_warn("unable to register IRQ domain\n");
>  
> +	err = irq_set_handler_data(parent_irq, intc);
> +	if (err)
> +		goto out;
> +
>  	setup_irq(parent_irq, &jz4740_cascade_action);
> -	return 0;
> +out:

Error handling in this function seems a bit lacking. Should it not be
freeing, iounmapping, and somehow freeing the generic irq chip as
appropriate for each of the error cases?

Cheers
James

> +	return err;
>  }
>  IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
> -- 
> 2.3.5
> 
> 

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

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

* Re: [PATCH v3 15/37] MIPS: JZ4740: remove jz_intc_base global
@ 2015-04-21 21:09     ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-21 21:09 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Thomas Gleixner, Jason Cooper

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

Hi Paul,

On Tue, Apr 21, 2015 at 03:46:42PM +0100, Paul Burton wrote:
> Avoid the need for the global variable jz_intc_base by introducing a
> struct ingenic_intc_data and passing it around as the IRQ handler data.
> 
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Jason Cooper <jason@lakedaemon.net>
> ---
> Changes in v3:
>   - New patch.
> ---
>  arch/mips/jz4740/irq.c | 35 ++++++++++++++++++++++++++---------
>  1 file changed, 26 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/mips/jz4740/irq.c b/arch/mips/jz4740/irq.c
> index 615eaa8..498ff28 100644
> --- a/arch/mips/jz4740/irq.c
> +++ b/arch/mips/jz4740/irq.c
> @@ -32,7 +32,9 @@
>  
>  #include "../../drivers/irqchip/irqchip.h"
>  
> -static void __iomem *jz_intc_base;
> +struct ingenic_intc_data {
> +	void __iomem *base;
> +};
>  
>  #define JZ_REG_INTC_STATUS	0x00
>  #define JZ_REG_INTC_MASK	0x04
> @@ -42,9 +44,10 @@ static void __iomem *jz_intc_base;
>  
>  static irqreturn_t jz4740_cascade(int irq, void *data)
>  {
> +	struct ingenic_intc_data *intc = irq_get_handler_data(irq);
>  	uint32_t irq_reg;
>  
> -	irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
> +	irq_reg = readl(intc->base + JZ_REG_INTC_PENDING);
>  
>  	if (irq_reg)
>  		generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
> @@ -80,21 +83,30 @@ static struct irqaction jz4740_cascade_action = {
>  static int __init jz4740_intc_of_init(struct device_node *node,
>  	struct device_node *parent)
>  {
> +	struct ingenic_intc_data *intc;
>  	struct irq_chip_generic *gc;
>  	struct irq_chip_type *ct;
>  	struct irq_domain *domain;
> -	int parent_irq;
> +	int parent_irq, err = 0;
> +
> +	intc = kzalloc(sizeof(*intc), GFP_KERNEL);
> +	if (!intc) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
>  
>  	parent_irq = irq_of_parse_and_map(node, 0);
> -	if (!parent_irq)
> -		return -EINVAL;
> +	if (!parent_irq) {
> +		err = -EINVAL;
> +		goto out;
> +	}
>  
> -	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
> +	intc->base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
>  
>  	/* Mask all irqs */
> -	writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
> +	writel(0xffffffff, intc->base + JZ_REG_INTC_SET_MASK);
>  
> -	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, jz_intc_base,
> +	gc = irq_alloc_generic_chip("INTC", 1, JZ4740_IRQ_BASE, intc->base,
>  		handle_level_irq);
>  
>  	gc->wake_enabled = IRQ_MSK(32);
> @@ -116,7 +128,12 @@ static int __init jz4740_intc_of_init(struct device_node *node,
>  	if (!domain)
>  		pr_warn("unable to register IRQ domain\n");
>  
> +	err = irq_set_handler_data(parent_irq, intc);
> +	if (err)
> +		goto out;
> +
>  	setup_irq(parent_irq, &jz4740_cascade_action);
> -	return 0;
> +out:

Error handling in this function seems a bit lacking. Should it not be
freeing, iounmapping, and somehow freeing the generic irq chip as
appropriate for each of the error cases?

Cheers
James

> +	return err;
>  }
>  IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", jz4740_intc_of_init);
> -- 
> 2.3.5
> 
> 

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

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

* Re: [PATCH v3 24/37] devicetree: add Ingenic CGU binding documentation
  2015-04-21 14:46     ` Paul Burton
  (?)
@ 2015-04-21 21:47         ` James Hogan
  -1 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-21 21:47 UTC (permalink / raw)
  To: Paul Burton
  Cc: linux-mips-6z/3iImG2C8G8FEW9MqTrA, Lars-Peter Clausen,
	Mike Turquette, devicetree-u79uwXL29TY76Z2rM5mHXA

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

On Tue, Apr 21, 2015 at 03:46:51PM +0100, Paul Burton wrote:
> Document the devicetree binding for Ingenic SoC CGUs, and add headers
> defining the clock specifiers for clocks provided by the JZ4740 & JZ4780
> CGU blocks.
> 
> Signed-off-by: Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
> Cc: Lars-Peter Clausen <lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
> Cc: Mike Turquette <mturquette-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> ---
> Changes in v3:
>   - Merge binding documentation for various Ingenic SoCs which differ only
>     by compatible strings.
> 
> Changes in v2:
>   - None.
> ---
>  .../devicetree/bindings/clock/ingenic,cgu.txt      | 53 +++++++++++++
>  include/dt-bindings/clock/jz4740-cgu.h             | 37 +++++++++
>  include/dt-bindings/clock/jz4780-cgu.h             | 88 ++++++++++++++++++++++
>  3 files changed, 178 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
>  create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
>  create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.txt b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
> new file mode 100644
> index 0000000..7421f8c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
> @@ -0,0 +1,53 @@
> +Ingenic SoC CGU binding
> +
> +The CGU in an Ingenic SoC provides all the clocks generated on-chip. It
> +typically includes a variety of PLLs, multiplexers, dividers & gates in order
> +to provide many different clock signals derived from only 2 external source
> +clocks.
> +
> +Required properties:
> +- compatible : Should be "ingenic,<soctype>-cgu".
> +  For example "ingenic,jz4740-cgu" or "ingenic,jz4780-cgu".
> +- reg : The address & length of the CGU registers.
> +- clocks : List of phandle & clock specifiers for clocks external to the TCU.

Suspect TCU is a typo for CGU.

Cheers
James

> +  Two such external clocks should be specified - first the external crystal
> +  "ext" and second the RTC clock source "rtc".
> +- clock-names : List of name strings for the external clocks.
> +- #clock-cells: Should be 1.
> +  Clock consumers specify this argument to identify a clock. The valid values
> +  may be found in <dt-bindings/clock/<soctype>-cgu.h>.
> +
> +Example SoC include file:
> +
> +/ {
> +	cgu: jz4740-cgu {
> +		compatible = "ingenic,jz4740-cgu";
> +		reg = <0x10000000 0x100>;
> +		#clock-cells = <1>;
> +	};
> +
> +	uart0: serial@10030000 {
> +		clocks = <&cgu JZ4740_CLK_UART0>;
> +	};
> +};
> +
> +Example board file:
> +
> +/ {
> +	ext: clock@0 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <12000000>;
> +	};
> +
> +	rtc: clock@1 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <32768>;
> +	};
> +
> +	&cgu {
> +		clocks = <&ext> <&rtc>;
> +		clock-names: "ext", "rtc";
> +	};
> +};
> diff --git a/include/dt-bindings/clock/jz4740-cgu.h b/include/dt-bindings/clock/jz4740-cgu.h
> new file mode 100644
> index 0000000..43153d3
> --- /dev/null
> +++ b/include/dt-bindings/clock/jz4740-cgu.h
> @@ -0,0 +1,37 @@
> +/*
> + * This header provides clock numbers for the ingenic,jz4740-cgu DT binding.
> + *
> + * They are roughly ordered as:
> + *   - external clocks
> + *   - PLLs
> + *   - muxes/dividers in the order they appear in the jz4740 programmers manual
> + *   - gates in order of their bit in the CLKGR* registers
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
> +#define __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
> +
> +#define JZ4740_CLK_EXT		0
> +#define JZ4740_CLK_RTC		1
> +#define JZ4740_CLK_PLL		2
> +#define JZ4740_CLK_PLL_HALF	3
> +#define JZ4740_CLK_CCLK		4
> +#define JZ4740_CLK_HCLK		5
> +#define JZ4740_CLK_PCLK		6
> +#define JZ4740_CLK_MCLK		7
> +#define JZ4740_CLK_LCD		8
> +#define JZ4740_CLK_LCD_PCLK	9
> +#define JZ4740_CLK_I2S		10
> +#define JZ4740_CLK_SPI		11
> +#define JZ4740_CLK_MMC		12
> +#define JZ4740_CLK_UHC		13
> +#define JZ4740_CLK_UDC		14
> +#define JZ4740_CLK_UART0	15
> +#define JZ4740_CLK_UART1	16
> +#define JZ4740_CLK_DMA		17
> +#define JZ4740_CLK_IPU		18
> +#define JZ4740_CLK_ADC		19
> +#define JZ4740_CLK_I2C		20
> +#define JZ4740_CLK_AIC		21
> +
> +#endif /* __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ */
> diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h
> new file mode 100644
> index 0000000..467165e
> --- /dev/null
> +++ b/include/dt-bindings/clock/jz4780-cgu.h
> @@ -0,0 +1,88 @@
> +/*
> + * This header provides clock numbers for the ingenic,jz4780-cgu DT binding.
> + *
> + * They are roughly ordered as:
> + *   - external clocks
> + *   - PLLs
> + *   - muxes/dividers in the order they appear in the jz4780 programmers manual
> + *   - gates in order of their bit in the CLKGR* registers
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
> +#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
> +
> +#define JZ4780_CLK_EXCLK	0
> +#define JZ4780_CLK_RTCLK	1
> +#define JZ4780_CLK_APLL		2
> +#define JZ4780_CLK_MPLL		3
> +#define JZ4780_CLK_EPLL		4
> +#define JZ4780_CLK_VPLL		5
> +#define JZ4780_CLK_OTGPHY	6
> +#define JZ4780_CLK_SCLKA	7
> +#define JZ4780_CLK_CPUMUX	8
> +#define JZ4780_CLK_CPU		9
> +#define JZ4780_CLK_L2CACHE	10
> +#define JZ4780_CLK_AHB0		11
> +#define JZ4780_CLK_AHB2PMUX	12
> +#define JZ4780_CLK_AHB2		13
> +#define JZ4780_CLK_PCLK		14
> +#define JZ4780_CLK_DDR		15
> +#define JZ4780_CLK_VPU		16
> +#define JZ4780_CLK_I2SPLL	17
> +#define JZ4780_CLK_I2S		18
> +#define JZ4780_CLK_LCD0PIXCLK	19
> +#define JZ4780_CLK_LCD1PIXCLK	20
> +#define JZ4780_CLK_MSCMUX	21
> +#define JZ4780_CLK_MSC0		22
> +#define JZ4780_CLK_MSC1		23
> +#define JZ4780_CLK_MSC2		24
> +#define JZ4780_CLK_UHC		25
> +#define JZ4780_CLK_SSIPLL	26
> +#define JZ4780_CLK_SSI		27
> +#define JZ4780_CLK_CIMMCLK	28
> +#define JZ4780_CLK_PCMPLL	29
> +#define JZ4780_CLK_PCM		30
> +#define JZ4780_CLK_GPU		31
> +#define JZ4780_CLK_HDMI		32
> +#define JZ4780_CLK_BCH		33
> +#define JZ4780_CLK_NEMC		34
> +#define JZ4780_CLK_OTG0		35
> +#define JZ4780_CLK_SSI0		36
> +#define JZ4780_CLK_SMB0		37
> +#define JZ4780_CLK_SMB1		38
> +#define JZ4780_CLK_SCC		39
> +#define JZ4780_CLK_AIC		40
> +#define JZ4780_CLK_TSSI0	41
> +#define JZ4780_CLK_OWI		42
> +#define JZ4780_CLK_KBC		43
> +#define JZ4780_CLK_SADC		44
> +#define JZ4780_CLK_UART0	45
> +#define JZ4780_CLK_UART1	46
> +#define JZ4780_CLK_UART2	47
> +#define JZ4780_CLK_UART3	48
> +#define JZ4780_CLK_SSI1		49
> +#define JZ4780_CLK_SSI2		50
> +#define JZ4780_CLK_PDMA		51
> +#define JZ4780_CLK_GPS		52
> +#define JZ4780_CLK_MAC		53
> +#define JZ4780_CLK_SMB2		54
> +#define JZ4780_CLK_CIM		55
> +#define JZ4780_CLK_LCD		56
> +#define JZ4780_CLK_TVE		57
> +#define JZ4780_CLK_IPU		58
> +#define JZ4780_CLK_DDR0		59
> +#define JZ4780_CLK_DDR1		60
> +#define JZ4780_CLK_SMB3		61
> +#define JZ4780_CLK_TSSI1	62
> +#define JZ4780_CLK_COMPRESS	63
> +#define JZ4780_CLK_AIC1		64
> +#define JZ4780_CLK_GPVLC	65
> +#define JZ4780_CLK_OTG1		66
> +#define JZ4780_CLK_UART4	67
> +#define JZ4780_CLK_AHBMON	68
> +#define JZ4780_CLK_SMB4		69
> +#define JZ4780_CLK_DES		70
> +#define JZ4780_CLK_X2D		71
> +#define JZ4780_CLK_CORE1	72
> +
> +#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */
> -- 
> 2.3.5
> 
> 

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

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

* Re: [PATCH v3 24/37] devicetree: add Ingenic CGU binding documentation
@ 2015-04-21 21:47         ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-21 21:47 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Mike Turquette, devicetree

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

On Tue, Apr 21, 2015 at 03:46:51PM +0100, Paul Burton wrote:
> Document the devicetree binding for Ingenic SoC CGUs, and add headers
> defining the clock specifiers for clocks provided by the JZ4740 & JZ4780
> CGU blocks.
> 
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Mike Turquette <mturquette@linaro.org>
> Cc: devicetree@vger.kernel.org
> ---
> Changes in v3:
>   - Merge binding documentation for various Ingenic SoCs which differ only
>     by compatible strings.
> 
> Changes in v2:
>   - None.
> ---
>  .../devicetree/bindings/clock/ingenic,cgu.txt      | 53 +++++++++++++
>  include/dt-bindings/clock/jz4740-cgu.h             | 37 +++++++++
>  include/dt-bindings/clock/jz4780-cgu.h             | 88 ++++++++++++++++++++++
>  3 files changed, 178 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
>  create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
>  create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.txt b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
> new file mode 100644
> index 0000000..7421f8c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
> @@ -0,0 +1,53 @@
> +Ingenic SoC CGU binding
> +
> +The CGU in an Ingenic SoC provides all the clocks generated on-chip. It
> +typically includes a variety of PLLs, multiplexers, dividers & gates in order
> +to provide many different clock signals derived from only 2 external source
> +clocks.
> +
> +Required properties:
> +- compatible : Should be "ingenic,<soctype>-cgu".
> +  For example "ingenic,jz4740-cgu" or "ingenic,jz4780-cgu".
> +- reg : The address & length of the CGU registers.
> +- clocks : List of phandle & clock specifiers for clocks external to the TCU.

Suspect TCU is a typo for CGU.

Cheers
James

> +  Two such external clocks should be specified - first the external crystal
> +  "ext" and second the RTC clock source "rtc".
> +- clock-names : List of name strings for the external clocks.
> +- #clock-cells: Should be 1.
> +  Clock consumers specify this argument to identify a clock. The valid values
> +  may be found in <dt-bindings/clock/<soctype>-cgu.h>.
> +
> +Example SoC include file:
> +
> +/ {
> +	cgu: jz4740-cgu {
> +		compatible = "ingenic,jz4740-cgu";
> +		reg = <0x10000000 0x100>;
> +		#clock-cells = <1>;
> +	};
> +
> +	uart0: serial@10030000 {
> +		clocks = <&cgu JZ4740_CLK_UART0>;
> +	};
> +};
> +
> +Example board file:
> +
> +/ {
> +	ext: clock@0 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <12000000>;
> +	};
> +
> +	rtc: clock@1 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <32768>;
> +	};
> +
> +	&cgu {
> +		clocks = <&ext> <&rtc>;
> +		clock-names: "ext", "rtc";
> +	};
> +};
> diff --git a/include/dt-bindings/clock/jz4740-cgu.h b/include/dt-bindings/clock/jz4740-cgu.h
> new file mode 100644
> index 0000000..43153d3
> --- /dev/null
> +++ b/include/dt-bindings/clock/jz4740-cgu.h
> @@ -0,0 +1,37 @@
> +/*
> + * This header provides clock numbers for the ingenic,jz4740-cgu DT binding.
> + *
> + * They are roughly ordered as:
> + *   - external clocks
> + *   - PLLs
> + *   - muxes/dividers in the order they appear in the jz4740 programmers manual
> + *   - gates in order of their bit in the CLKGR* registers
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
> +#define __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
> +
> +#define JZ4740_CLK_EXT		0
> +#define JZ4740_CLK_RTC		1
> +#define JZ4740_CLK_PLL		2
> +#define JZ4740_CLK_PLL_HALF	3
> +#define JZ4740_CLK_CCLK		4
> +#define JZ4740_CLK_HCLK		5
> +#define JZ4740_CLK_PCLK		6
> +#define JZ4740_CLK_MCLK		7
> +#define JZ4740_CLK_LCD		8
> +#define JZ4740_CLK_LCD_PCLK	9
> +#define JZ4740_CLK_I2S		10
> +#define JZ4740_CLK_SPI		11
> +#define JZ4740_CLK_MMC		12
> +#define JZ4740_CLK_UHC		13
> +#define JZ4740_CLK_UDC		14
> +#define JZ4740_CLK_UART0	15
> +#define JZ4740_CLK_UART1	16
> +#define JZ4740_CLK_DMA		17
> +#define JZ4740_CLK_IPU		18
> +#define JZ4740_CLK_ADC		19
> +#define JZ4740_CLK_I2C		20
> +#define JZ4740_CLK_AIC		21
> +
> +#endif /* __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ */
> diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h
> new file mode 100644
> index 0000000..467165e
> --- /dev/null
> +++ b/include/dt-bindings/clock/jz4780-cgu.h
> @@ -0,0 +1,88 @@
> +/*
> + * This header provides clock numbers for the ingenic,jz4780-cgu DT binding.
> + *
> + * They are roughly ordered as:
> + *   - external clocks
> + *   - PLLs
> + *   - muxes/dividers in the order they appear in the jz4780 programmers manual
> + *   - gates in order of their bit in the CLKGR* registers
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
> +#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
> +
> +#define JZ4780_CLK_EXCLK	0
> +#define JZ4780_CLK_RTCLK	1
> +#define JZ4780_CLK_APLL		2
> +#define JZ4780_CLK_MPLL		3
> +#define JZ4780_CLK_EPLL		4
> +#define JZ4780_CLK_VPLL		5
> +#define JZ4780_CLK_OTGPHY	6
> +#define JZ4780_CLK_SCLKA	7
> +#define JZ4780_CLK_CPUMUX	8
> +#define JZ4780_CLK_CPU		9
> +#define JZ4780_CLK_L2CACHE	10
> +#define JZ4780_CLK_AHB0		11
> +#define JZ4780_CLK_AHB2PMUX	12
> +#define JZ4780_CLK_AHB2		13
> +#define JZ4780_CLK_PCLK		14
> +#define JZ4780_CLK_DDR		15
> +#define JZ4780_CLK_VPU		16
> +#define JZ4780_CLK_I2SPLL	17
> +#define JZ4780_CLK_I2S		18
> +#define JZ4780_CLK_LCD0PIXCLK	19
> +#define JZ4780_CLK_LCD1PIXCLK	20
> +#define JZ4780_CLK_MSCMUX	21
> +#define JZ4780_CLK_MSC0		22
> +#define JZ4780_CLK_MSC1		23
> +#define JZ4780_CLK_MSC2		24
> +#define JZ4780_CLK_UHC		25
> +#define JZ4780_CLK_SSIPLL	26
> +#define JZ4780_CLK_SSI		27
> +#define JZ4780_CLK_CIMMCLK	28
> +#define JZ4780_CLK_PCMPLL	29
> +#define JZ4780_CLK_PCM		30
> +#define JZ4780_CLK_GPU		31
> +#define JZ4780_CLK_HDMI		32
> +#define JZ4780_CLK_BCH		33
> +#define JZ4780_CLK_NEMC		34
> +#define JZ4780_CLK_OTG0		35
> +#define JZ4780_CLK_SSI0		36
> +#define JZ4780_CLK_SMB0		37
> +#define JZ4780_CLK_SMB1		38
> +#define JZ4780_CLK_SCC		39
> +#define JZ4780_CLK_AIC		40
> +#define JZ4780_CLK_TSSI0	41
> +#define JZ4780_CLK_OWI		42
> +#define JZ4780_CLK_KBC		43
> +#define JZ4780_CLK_SADC		44
> +#define JZ4780_CLK_UART0	45
> +#define JZ4780_CLK_UART1	46
> +#define JZ4780_CLK_UART2	47
> +#define JZ4780_CLK_UART3	48
> +#define JZ4780_CLK_SSI1		49
> +#define JZ4780_CLK_SSI2		50
> +#define JZ4780_CLK_PDMA		51
> +#define JZ4780_CLK_GPS		52
> +#define JZ4780_CLK_MAC		53
> +#define JZ4780_CLK_SMB2		54
> +#define JZ4780_CLK_CIM		55
> +#define JZ4780_CLK_LCD		56
> +#define JZ4780_CLK_TVE		57
> +#define JZ4780_CLK_IPU		58
> +#define JZ4780_CLK_DDR0		59
> +#define JZ4780_CLK_DDR1		60
> +#define JZ4780_CLK_SMB3		61
> +#define JZ4780_CLK_TSSI1	62
> +#define JZ4780_CLK_COMPRESS	63
> +#define JZ4780_CLK_AIC1		64
> +#define JZ4780_CLK_GPVLC	65
> +#define JZ4780_CLK_OTG1		66
> +#define JZ4780_CLK_UART4	67
> +#define JZ4780_CLK_AHBMON	68
> +#define JZ4780_CLK_SMB4		69
> +#define JZ4780_CLK_DES		70
> +#define JZ4780_CLK_X2D		71
> +#define JZ4780_CLK_CORE1	72
> +
> +#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */
> -- 
> 2.3.5
> 
> 

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

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

* Re: [PATCH v3 24/37] devicetree: add Ingenic CGU binding documentation
@ 2015-04-21 21:47         ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-21 21:47 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Mike Turquette, devicetree

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

On Tue, Apr 21, 2015 at 03:46:51PM +0100, Paul Burton wrote:
> Document the devicetree binding for Ingenic SoC CGUs, and add headers
> defining the clock specifiers for clocks provided by the JZ4740 & JZ4780
> CGU blocks.
> 
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Mike Turquette <mturquette@linaro.org>
> Cc: devicetree@vger.kernel.org
> ---
> Changes in v3:
>   - Merge binding documentation for various Ingenic SoCs which differ only
>     by compatible strings.
> 
> Changes in v2:
>   - None.
> ---
>  .../devicetree/bindings/clock/ingenic,cgu.txt      | 53 +++++++++++++
>  include/dt-bindings/clock/jz4740-cgu.h             | 37 +++++++++
>  include/dt-bindings/clock/jz4780-cgu.h             | 88 ++++++++++++++++++++++
>  3 files changed, 178 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
>  create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
>  create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.txt b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
> new file mode 100644
> index 0000000..7421f8c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.txt
> @@ -0,0 +1,53 @@
> +Ingenic SoC CGU binding
> +
> +The CGU in an Ingenic SoC provides all the clocks generated on-chip. It
> +typically includes a variety of PLLs, multiplexers, dividers & gates in order
> +to provide many different clock signals derived from only 2 external source
> +clocks.
> +
> +Required properties:
> +- compatible : Should be "ingenic,<soctype>-cgu".
> +  For example "ingenic,jz4740-cgu" or "ingenic,jz4780-cgu".
> +- reg : The address & length of the CGU registers.
> +- clocks : List of phandle & clock specifiers for clocks external to the TCU.

Suspect TCU is a typo for CGU.

Cheers
James

> +  Two such external clocks should be specified - first the external crystal
> +  "ext" and second the RTC clock source "rtc".
> +- clock-names : List of name strings for the external clocks.
> +- #clock-cells: Should be 1.
> +  Clock consumers specify this argument to identify a clock. The valid values
> +  may be found in <dt-bindings/clock/<soctype>-cgu.h>.
> +
> +Example SoC include file:
> +
> +/ {
> +	cgu: jz4740-cgu {
> +		compatible = "ingenic,jz4740-cgu";
> +		reg = <0x10000000 0x100>;
> +		#clock-cells = <1>;
> +	};
> +
> +	uart0: serial@10030000 {
> +		clocks = <&cgu JZ4740_CLK_UART0>;
> +	};
> +};
> +
> +Example board file:
> +
> +/ {
> +	ext: clock@0 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <12000000>;
> +	};
> +
> +	rtc: clock@1 {
> +		compatible = "fixed-clock";
> +		#clock-cells = <0>;
> +		clock-frequency = <32768>;
> +	};
> +
> +	&cgu {
> +		clocks = <&ext> <&rtc>;
> +		clock-names: "ext", "rtc";
> +	};
> +};
> diff --git a/include/dt-bindings/clock/jz4740-cgu.h b/include/dt-bindings/clock/jz4740-cgu.h
> new file mode 100644
> index 0000000..43153d3
> --- /dev/null
> +++ b/include/dt-bindings/clock/jz4740-cgu.h
> @@ -0,0 +1,37 @@
> +/*
> + * This header provides clock numbers for the ingenic,jz4740-cgu DT binding.
> + *
> + * They are roughly ordered as:
> + *   - external clocks
> + *   - PLLs
> + *   - muxes/dividers in the order they appear in the jz4740 programmers manual
> + *   - gates in order of their bit in the CLKGR* registers
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
> +#define __DT_BINDINGS_CLOCK_JZ4740_CGU_H__
> +
> +#define JZ4740_CLK_EXT		0
> +#define JZ4740_CLK_RTC		1
> +#define JZ4740_CLK_PLL		2
> +#define JZ4740_CLK_PLL_HALF	3
> +#define JZ4740_CLK_CCLK		4
> +#define JZ4740_CLK_HCLK		5
> +#define JZ4740_CLK_PCLK		6
> +#define JZ4740_CLK_MCLK		7
> +#define JZ4740_CLK_LCD		8
> +#define JZ4740_CLK_LCD_PCLK	9
> +#define JZ4740_CLK_I2S		10
> +#define JZ4740_CLK_SPI		11
> +#define JZ4740_CLK_MMC		12
> +#define JZ4740_CLK_UHC		13
> +#define JZ4740_CLK_UDC		14
> +#define JZ4740_CLK_UART0	15
> +#define JZ4740_CLK_UART1	16
> +#define JZ4740_CLK_DMA		17
> +#define JZ4740_CLK_IPU		18
> +#define JZ4740_CLK_ADC		19
> +#define JZ4740_CLK_I2C		20
> +#define JZ4740_CLK_AIC		21
> +
> +#endif /* __DT_BINDINGS_CLOCK_JZ4740_CGU_H__ */
> diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h
> new file mode 100644
> index 0000000..467165e
> --- /dev/null
> +++ b/include/dt-bindings/clock/jz4780-cgu.h
> @@ -0,0 +1,88 @@
> +/*
> + * This header provides clock numbers for the ingenic,jz4780-cgu DT binding.
> + *
> + * They are roughly ordered as:
> + *   - external clocks
> + *   - PLLs
> + *   - muxes/dividers in the order they appear in the jz4780 programmers manual
> + *   - gates in order of their bit in the CLKGR* registers
> + */
> +
> +#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
> +#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
> +
> +#define JZ4780_CLK_EXCLK	0
> +#define JZ4780_CLK_RTCLK	1
> +#define JZ4780_CLK_APLL		2
> +#define JZ4780_CLK_MPLL		3
> +#define JZ4780_CLK_EPLL		4
> +#define JZ4780_CLK_VPLL		5
> +#define JZ4780_CLK_OTGPHY	6
> +#define JZ4780_CLK_SCLKA	7
> +#define JZ4780_CLK_CPUMUX	8
> +#define JZ4780_CLK_CPU		9
> +#define JZ4780_CLK_L2CACHE	10
> +#define JZ4780_CLK_AHB0		11
> +#define JZ4780_CLK_AHB2PMUX	12
> +#define JZ4780_CLK_AHB2		13
> +#define JZ4780_CLK_PCLK		14
> +#define JZ4780_CLK_DDR		15
> +#define JZ4780_CLK_VPU		16
> +#define JZ4780_CLK_I2SPLL	17
> +#define JZ4780_CLK_I2S		18
> +#define JZ4780_CLK_LCD0PIXCLK	19
> +#define JZ4780_CLK_LCD1PIXCLK	20
> +#define JZ4780_CLK_MSCMUX	21
> +#define JZ4780_CLK_MSC0		22
> +#define JZ4780_CLK_MSC1		23
> +#define JZ4780_CLK_MSC2		24
> +#define JZ4780_CLK_UHC		25
> +#define JZ4780_CLK_SSIPLL	26
> +#define JZ4780_CLK_SSI		27
> +#define JZ4780_CLK_CIMMCLK	28
> +#define JZ4780_CLK_PCMPLL	29
> +#define JZ4780_CLK_PCM		30
> +#define JZ4780_CLK_GPU		31
> +#define JZ4780_CLK_HDMI		32
> +#define JZ4780_CLK_BCH		33
> +#define JZ4780_CLK_NEMC		34
> +#define JZ4780_CLK_OTG0		35
> +#define JZ4780_CLK_SSI0		36
> +#define JZ4780_CLK_SMB0		37
> +#define JZ4780_CLK_SMB1		38
> +#define JZ4780_CLK_SCC		39
> +#define JZ4780_CLK_AIC		40
> +#define JZ4780_CLK_TSSI0	41
> +#define JZ4780_CLK_OWI		42
> +#define JZ4780_CLK_KBC		43
> +#define JZ4780_CLK_SADC		44
> +#define JZ4780_CLK_UART0	45
> +#define JZ4780_CLK_UART1	46
> +#define JZ4780_CLK_UART2	47
> +#define JZ4780_CLK_UART3	48
> +#define JZ4780_CLK_SSI1		49
> +#define JZ4780_CLK_SSI2		50
> +#define JZ4780_CLK_PDMA		51
> +#define JZ4780_CLK_GPS		52
> +#define JZ4780_CLK_MAC		53
> +#define JZ4780_CLK_SMB2		54
> +#define JZ4780_CLK_CIM		55
> +#define JZ4780_CLK_LCD		56
> +#define JZ4780_CLK_TVE		57
> +#define JZ4780_CLK_IPU		58
> +#define JZ4780_CLK_DDR0		59
> +#define JZ4780_CLK_DDR1		60
> +#define JZ4780_CLK_SMB3		61
> +#define JZ4780_CLK_TSSI1	62
> +#define JZ4780_CLK_COMPRESS	63
> +#define JZ4780_CLK_AIC1		64
> +#define JZ4780_CLK_GPVLC	65
> +#define JZ4780_CLK_OTG1		66
> +#define JZ4780_CLK_UART4	67
> +#define JZ4780_CLK_AHBMON	68
> +#define JZ4780_CLK_SMB4		69
> +#define JZ4780_CLK_DES		70
> +#define JZ4780_CLK_X2D		71
> +#define JZ4780_CLK_CORE1	72
> +
> +#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */
> -- 
> 2.3.5
> 
> 

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

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

* Re: [PATCH v3 25/37] clk: ingenic: add driver for Ingenic SoC CGU clocks
@ 2015-04-21 23:25     ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-21 23:25 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Mike Turquette

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

Hi Paul,

On Tue, Apr 21, 2015 at 03:46:52PM +0100, Paul Burton wrote:
> This driver supports the CGU clocks for Ingenic SoCs. It is generic
> enough to be usable across at least the JZ4740 to the JZ4780, and will
> be made use of on such devices in subsequent commits. This patch by
> itself only adds the SoC-agnostic infrastructure that forms the bulk of
> the CGU driver for the aforementioned further commits to make use of.
> 
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Co-authored-by: Paul Cercueil <paul@crapouillou.net>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Mike Turquette <mturquette@linaro.org>
> ---
> Changes in v3:
>   - s/jz47xx/ingenic/ since Ingenic have changed their naming scheme to
>     "Mxxx" for newer SoCs.
> 
>   - Allow clock gating with registers other than CLKGR* (pcercuei).
> 
>   - Fixup dividers to never exceed the requested rate (pcercuei).
> 
>   - Fixup PLL calculations to work better with more restricted
>     coefficient bit widths (pcercuei).
> 
> Changes in v2:
>   - Fix spinlock handling in jz47xx_clk_set_rate error path (ZubairLK).
> ---
>  drivers/clk/Makefile         |   1 +
>  drivers/clk/ingenic/Makefile |   1 +
>  drivers/clk/ingenic/cgu.c    | 711 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/ingenic/cgu.h    | 223 ++++++++++++++
>  4 files changed, 936 insertions(+)
>  create mode 100644 drivers/clk/ingenic/Makefile
>  create mode 100644 drivers/clk/ingenic/cgu.c
>  create mode 100644 drivers/clk/ingenic/cgu.h
> 
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 3d00c25..cc77327 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -50,6 +50,7 @@ obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
>  obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
>  obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
>  obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
> +obj-$(CONFIG_MACH_INGENIC)		+= ingenic/
>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
>  ifeq ($(CONFIG_COMMON_CLK), y)
>  obj-$(CONFIG_ARCH_MMP)			+= mmp/
> diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
> new file mode 100644
> index 0000000..5ac2fd9
> --- /dev/null
> +++ b/drivers/clk/ingenic/Makefile
> @@ -0,0 +1 @@
> +obj-y				+= cgu.o
> diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
> new file mode 100644
> index 0000000..81a720e
> --- /dev/null
> +++ b/drivers/clk/ingenic/cgu.c
> @@ -0,0 +1,713 @@
> +/*
> + * Ingenic SoC CGU driver
> + *
> + * Copyright (c) 2013-2015 Imagination Technologies
> + * Author: Paul Burton <paul.burton@imgtec.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include "cgu.h"
> +
> +#define MHZ (1000 * 1000)
> +
> +/**
> + * ingenic_cgu_gate_get - get the value of clock gate register bit

I think you should have "()" in there because its a function (if
Documentation/kernel-doc-nano-HOWTO.txt is anything to go by).

> + * @cgu: reference to the CGU whose registers should be read
> + * @idx: index of the gate bit

Stale

> + *
> + * Returns 1 if the gate bit is set, else 0. The index begins with 0 being

I believe its common for return value to have its own section at the
end, which shows up nicer in the output, e.g.

 * The index begins with 0 being bit 0 of CLKGR0, continuing from 32 for
 * bit 0 of CLKGR1 etc. For example, the index of bit 9 of CLKGR1 would
 * be (32+9) == 41.
 *
 * The caller must hold cgu->power_lock.
 *
 * Return: 1 if the gate bit is set, else 0.

> + * bit 0 of CLKGR0, continuing from 32 for bit 0 of CLKGR1 etc. For example,
> + * the index of bit 9 of CLKGR1 would be (32+9) == 41.

I'm guessing that's a bit stale too.

> + *
> + * The caller must hold cgu->power_lock.
> + */
> +static inline unsigned

maybe return bool and scrap the !!(

> +ingenic_cgu_gate_get(struct ingenic_cgu *cgu,
> +		     const struct ingenic_cgu_gate_info *info)
> +{
> +	return !!(readl(cgu->base + info->reg) & BIT(info->bit));
> +}
> +
> +/**
> + * ingenic_cgu_gate_set - set the value of clock gate register bit
> + * @cgu: reference to the CGU whose registers should be modified
> + * @idx: index of the gate bit
> + * @val: non-zero to gate a clock, otherwise zero
> + *
> + * Sets the given gate bit in order to gate or ungate a clock. See
> + * ingenic_cgu_gate_get for a description of the idx parameter.
> + *
> + * The caller must hold cgu->power_lock.
> + */

same as above

> +static inline void
> +ingenic_cgu_gate_set(struct ingenic_cgu *cgu,
> +		     const struct ingenic_cgu_gate_info *info, bool val)
> +{
> +	u32 clkgr = readl(cgu->base + info->reg);
> +
> +	if (val)
> +		clkgr |= BIT(info->bit);

Don't forget
#include <linux/bitops.h>
for BIT() and GENMASK()

> +	else
> +		clkgr &= ~BIT(info->bit);
> +
> +	writel(clkgr, cgu->base + info->reg);
> +}
> +
> +/*
> + * PLL operations
> + */
> +
> +static unsigned long
> +ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	const struct ingenic_cgu_pll_info *pll_info;
> +	unsigned m, n, od_enc, od;
> +	bool bypass, enable;
> +	unsigned long flags;
> +	u32 ctl;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +	BUG_ON(clk_info->type != CGU_CLK_PLL);
> +	pll_info = &clk_info->pll;
> +
> +	spin_lock_irqsave(&cgu->pll_lock, flags);
> +	ctl = readl(cgu->base + pll_info->reg);
> +	spin_unlock_irqrestore(&cgu->pll_lock, flags);
> +
> +	m = ((ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0));
> +	m += pll_info->m_offset;
> +	n = ((ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0));
> +	n += pll_info->n_offset;
> +	od_enc = ctl >> pll_info->od_shift;
> +	od_enc &= GENMASK(pll_info->od_bits - 1, 0);
> +	bypass = !!(ctl & BIT(pll_info->bypass_bit));
> +	enable = !!(ctl & BIT(pll_info->enable_bit));
> +
> +	if (bypass)
> +		return parent_rate;
> +
> +	if (!enable)
> +		return 0;
> +
> +	for (od = 0; od < pll_info->od_max; od++) {
> +		if (pll_info->od_encoding[od] == od_enc)
> +			break;
> +	}
> +	BUG_ON(od == pll_info->od_max);
> +	od++;
> +
> +	return parent_rate * m / (n * od);

In the worst case for jz4740 looking a couple of patches ahead, raw m
can be as high as 0x1ff, offset to 0x201 = 513. That means parent_rate
must be < 8.37MHz to avoid overflow. TZ1090 PLL (which looks
conceptually similar) does this:

f_out = div_u64((u64)f_in * clk_f,
		2 * clk_r * clk_od);

https://lkml.org/lkml/2014/12/1/832

> +}
> +
> +static unsigned long
> +ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
> +		 unsigned long rate, unsigned long parent_rate,
> +		 unsigned *pm, unsigned *pn, unsigned *pod)
> +{
> +	unsigned m, n, od;
> +
> +	od = 1;
> +
> +	/*
> +	 * The frequency after the input divider must be between 10 and 50 MHz.
> +	 * The highest divider yields the best resolution.
> +	 */
> +	n = parent_rate / (10 * MHZ);
> +	n = min_t(unsigned, n, 1 << clk_info->pll.n_bits);
> +	n = max_t(unsigned, n, 1);
> +
> +	m = (rate / MHZ) * od * n / (parent_rate / MHZ);
> +	m = min_t(unsigned, m, 1 << clk_info->pll.m_bits);
> +	m = max_t(unsigned, m, 1);

These appear to assume m_offset & n_offset are both 1.

> +
> +	if (pm)
> +		*pm = m;
> +	if (pn)
> +		*pn = n;
> +	if (pod)
> +		*pod = od;
> +
> +	return parent_rate * m / (n * od);

same again


You may want to consider a more brute force approach like TZ1090 does at
some point, for maximum accuracy and to avoid problems when output is
fed back in as input and gives a different result:

rate = clk_round_rate(clk, desired);
clk_set_rate(clk, rate);
actual_rate = clk_get_rate(clk);

rate != actual_rate

I can't tell from a superficial glance whether its vulnerable to that
problem.

> +}
> +
> +static long
> +ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
> +		       unsigned long *prate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +	BUG_ON(clk_info->type != CGU_CLK_PLL);
> +
> +	return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
> +}
> +
> +static int
> +ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
> +		     unsigned long parent_rate)
> +{
> +	const unsigned timeout = 100;
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	const struct ingenic_cgu_pll_info *pll_info;
> +	unsigned long rate, flags;
> +	unsigned m, n, od, i;
> +	u32 ctl;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +	BUG_ON(clk_info->type != CGU_CLK_PLL);
> +	pll_info = &clk_info->pll;
> +
> +	rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
> +			       &m, &n, &od);
> +	if (rate != req_rate)
> +		pr_info("ingenic-cgu: request '%s' rate %luHz, actual %luHz\n",
> +			clk_info->name, req_rate, rate);
> +
> +	spin_lock_irqsave(&cgu->pll_lock, flags);
> +	ctl = readl(cgu->base + pll_info->reg);
> +
> +	ctl &= ~(GENMASK(pll_info->m_bits - 1, 0) << pll_info->m_shift);
> +	ctl |= (m - pll_info->m_offset) << pll_info->m_shift;
> +
> +	ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift);
> +	ctl |= (n - pll_info->n_offset) << pll_info->n_shift;
> +
> +	ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
> +	ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
> +
> +	ctl &= ~BIT(pll_info->bypass_bit);
> +	ctl |= BIT(pll_info->enable_bit);
> +
> +	writel(ctl, cgu->base + pll_info->reg);
> +
> +	/* wait for the PLL to stabilise */
> +	for (i = 0; i < timeout; i++) {
> +		ctl = readl(cgu->base + pll_info->reg);
> +		if (ctl & BIT(pll_info->stable_bit))
> +			break;
> +		mdelay(1);
> +	}
> +
> +	spin_unlock_irqrestore(&cgu->pll_lock, flags);
> +
> +	if (i == timeout)
> +		return -EBUSY;
> +
> +	return 0;
> +}
> +
> +static const struct clk_ops ingenic_pll_ops = {
> +	.recalc_rate = ingenic_pll_recalc_rate,
> +	.round_rate = ingenic_pll_round_rate,
> +	.set_rate = ingenic_pll_set_rate,
> +};
> +
> +/*
> + * Operations for all non-PLL clocks
> + */
> +
> +static u8 ingenic_clk_get_parent(struct clk_hw *hw)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	u32 reg;
> +	u8 i, hw_idx, idx = 0;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_MUX) {
> +		reg = readl(cgu->base + clk_info->mux.reg);
> +		hw_idx = (reg >> clk_info->mux.shift) &
> +			 ((1 << clk_info->mux.bits) - 1);

Looks like a good place for GENMASK like elsewhere. Maybe same in a few
places below.

> +
> +		/*
> +		 * Convert the hardware index to the parent index by skipping
> +		 * over any -1's in the parents array.
> +		 */
> +		for (i = 0; i < hw_idx; i++) {
> +			if (clk_info->parents[i] != -1)
> +				idx++;
> +		}
> +	}
> +
> +	return idx;
> +}
> +
> +static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long flags;
> +	u8 curr_idx, hw_idx, num_poss;
> +	u32 reg, mask;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_MUX) {
> +		/*
> +		 * Convert the parent index to the hardware index by adding
> +		 * 1 for any -1 in the parents array preceding the given
> +		 * index. That is, we want the index of idx'th entry in
> +		 * clk_info->parents which does not equal -1.
> +		 */
> +		hw_idx = curr_idx = 0;
> +		num_poss = 1 << clk_info->mux.bits;
> +		for (; (hw_idx < num_poss) && (curr_idx != idx); hw_idx++) {

if idx==0, this'll never iterate since curr_idx starts at 0, even if the
first parent is -1. It's basically an off-by-one error I think.

> +			if (clk_info->parents[hw_idx] == -1)
> +				continue;
> +			curr_idx++;

maybe move the curr_idx == idx check here.

> +		}
> +
> +		/* idx should always be a valid parent */
> +		BUG_ON(curr_idx != idx);

Hmm, i suppose. BUG_ON(hw_idx == num_poss) looks more direct/intuitive
to me, but probably subjective.

> +
> +		mask = ((1 << clk_info->mux.bits) - 1) << clk_info->mux.shift;
> +
> +		spin_lock_irqsave(&cgu->divmux_lock, flags);
> +
> +		/* write the register */
> +		reg = readl(cgu->base + clk_info->mux.reg);
> +		reg &= ~mask;
> +		reg |= hw_idx << clk_info->mux.shift;
> +		writel(reg, cgu->base + clk_info->mux.reg);
> +
> +		spin_unlock_irqrestore(&cgu->divmux_lock, flags);
> +		return 0;
> +	}
> +
> +	return idx ? -EINVAL : 0;
> +}
> +
> +static unsigned long
> +ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long rate = parent_rate;
> +	u32 div_reg, div;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_DIV) {
> +		div_reg = readl(cgu->base + clk_info->div.reg);
> +		div = (div_reg >> clk_info->div.shift) &
> +		      ((1 << clk_info->div.bits) - 1);
> +		div += 1;
> +
> +		rate /= div;
> +	}
> +
> +	return rate;
> +}
> +
> +static unsigned
> +ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info,
> +		     unsigned long parent_rate, unsigned long req_rate)
> +{
> +	unsigned div;
> +
> +	/* calculate the divide */
> +	div = DIV_ROUND_UP(parent_rate, req_rate);
> +
> +	/* and impose hardware constraints */
> +	div = min_t(unsigned, div, 1 << clk_info->div.bits);
> +	div = max_t(unsigned, div, 1);
> +
> +	return div;
> +}
> +
> +static long
> +ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
> +		       unsigned long *parent_rate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	long rate = req_rate;

should the default be *parent_rate?

> +	unsigned div;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_DIV) {
> +		div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
> +		rate = *parent_rate / div;
> +	} else if (clk_info->type & CGU_CLK_FIXDIV) {
> +		rate = *parent_rate / clk_info->fixdiv.div;
> +	}
> +
> +	return rate;
> +}
> +
> +static int
> +ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
> +		     unsigned long parent_rate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	const unsigned timeout = 100;
> +	unsigned long rate, flags;
> +	unsigned div, i;
> +	u32 reg, mask;
> +	int ret = 0;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_DIV) {
> +		div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate);
> +		rate = parent_rate / div;
> +
> +		if (rate != req_rate)
> +			return -EINVAL;
> +
> +		spin_lock_irqsave(&cgu->divmux_lock, flags);
> +		reg = readl(cgu->base + clk_info->div.reg);
> +
> +		/* update the divide */
> +		mask = (1 << clk_info->div.bits) - 1;
> +		reg &= ~(mask << clk_info->div.shift);
> +		reg |= (div - 1) << clk_info->div.shift;
> +
> +		/* clear the stop bit */
> +		if (clk_info->div.stop_bit != -1)
> +			reg &= ~(1 << clk_info->div.stop_bit);

BIT() (same for a couple of cases below)

> +
> +		/* set the change enable bit */
> +		if (clk_info->div.ce_bit != -1)
> +			reg |= 1 << clk_info->div.ce_bit;
> +
> +		/* update the hardware */
> +		writel(reg, cgu->base + clk_info->div.reg);
> +
> +		/* wait for the change to take effect */
> +		if (clk_info->div.busy_bit != -1) {
> +			for (i = 0; i < timeout; i++) {
> +				reg = readl(cgu->base + clk_info->div.reg);
> +				if (!(reg & (1 << clk_info->div.busy_bit)))
> +					break;
> +				mdelay(1);
> +			}
> +			if (i == timeout)
> +				ret = -EBUSY;
> +		}
> +
> +		spin_unlock_irqrestore(&cgu->divmux_lock, flags);

Is the main common clk lock & mutex insufficient? Setting rate appears
to take a mutex anyway, so you're already not in atomic context, in
which case maybe s/mdelay/msleep/ throughout if you can get rid of the
locks.

Its getting late. I'll continue looking at this patch some other time.

Cheers
James

> +		return ret;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int ingenic_clk_enable(struct clk_hw *hw)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long flags;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_GATE) {
> +		/* ungate the clock */
> +		spin_lock_irqsave(&cgu->power_lock, flags);
> +		ingenic_cgu_gate_set(cgu, &clk_info->gate, false);
> +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> +	}
> +
> +	return 0;
> +}
> +
> +static void ingenic_clk_disable(struct clk_hw *hw)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long flags;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_GATE) {
> +		/* gate the clock */
> +		spin_lock_irqsave(&cgu->power_lock, flags);
> +		ingenic_cgu_gate_set(cgu, &clk_info->gate, true);
> +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> +	}
> +}
> +
> +static int ingenic_clk_is_enabled(struct clk_hw *hw)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long flags;
> +	int enabled = 1;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_GATE) {
> +		spin_lock_irqsave(&cgu->power_lock, flags);
> +		enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
> +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> +	}
> +
> +	return enabled;
> +}
> +
> +static const struct clk_ops ingenic_clk_ops = {
> +	.get_parent = ingenic_clk_get_parent,
> +	.set_parent = ingenic_clk_set_parent,
> +
> +	.recalc_rate = ingenic_clk_recalc_rate,
> +	.round_rate = ingenic_clk_round_rate,
> +	.set_rate = ingenic_clk_set_rate,
> +
> +	.enable = ingenic_clk_enable,
> +	.disable = ingenic_clk_disable,
> +	.is_enabled = ingenic_clk_is_enabled,
> +};
> +
> +/*
> + * Setup functions.
> + */
> +
> +static int register_clock(struct ingenic_cgu *cgu, unsigned idx)
> +{
> +	const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx];
> +	struct clk_init_data clk_init;
> +	struct ingenic_clk *ingenic_clk = NULL;
> +	struct clk *clk, *parent;
> +	const char *parent_names[4];
> +	unsigned caps, i, num_possible;
> +	int err = -EINVAL;
> +
> +	BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names));
> +
> +	if (clk_info->type == CGU_CLK_EXT) {
> +		clk = of_clk_get_by_name(cgu->np, clk_info->name);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: no external clock '%s' provided\n",
> +			       __func__, clk_info->name);
> +			err = -ENODEV;
> +			goto out;
> +		}
> +		err = clk_register_clkdev(clk, clk_info->name, NULL);
> +		if (err) {
> +			clk_put(clk);
> +			goto out;
> +		}
> +		cgu->clocks.clks[idx] = clk;
> +		return 0;
> +	}
> +
> +	if (!clk_info->type) {
> +		pr_err("%s: no clock type specified for '%s'\n", __func__,
> +		       clk_info->name);
> +		goto out;
> +	}
> +
> +	ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL);
> +	if (!ingenic_clk) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +
> +	ingenic_clk->hw.init = &clk_init;
> +	ingenic_clk->cgu = cgu;
> +	ingenic_clk->idx = idx;
> +
> +	clk_init.name = clk_info->name;
> +	clk_init.flags = 0;
> +	clk_init.parent_names = parent_names;
> +
> +	caps = clk_info->type;
> +
> +	if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
> +		clk_init.num_parents = 0;
> +
> +		if (caps & CGU_CLK_MUX)
> +			num_possible = 1 << clk_info->mux.bits;
> +		else
> +			num_possible = ARRAY_SIZE(clk_info->parents);
> +
> +		for (i = 0; i < num_possible; i++) {
> +			if (clk_info->parents[i] == -1)
> +				continue;
> +
> +			parent = cgu->clocks.clks[clk_info->parents[i]];
> +			parent_names[clk_init.num_parents] =
> +				__clk_get_name(parent);
> +			clk_init.num_parents++;
> +		}
> +
> +		BUG_ON(!clk_init.num_parents);
> +		BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names));
> +	} else {
> +		BUG_ON(clk_info->parents[0] == -1);
> +		clk_init.num_parents = 1;
> +		parent = cgu->clocks.clks[clk_info->parents[0]];
> +		parent_names[0] = __clk_get_name(parent);
> +	}
> +
> +	if (caps & CGU_CLK_CUSTOM) {
> +		clk_init.ops = clk_info->custom.clk_ops;
> +
> +		caps &= ~CGU_CLK_CUSTOM;
> +
> +		if (caps) {
> +			pr_err("%s: custom clock may not be combined with type 0x%x\n",
> +			       __func__, caps);
> +			goto out;
> +		}
> +	} else if (caps & CGU_CLK_PLL) {
> +		clk_init.ops = &ingenic_pll_ops;
> +
> +		caps &= ~CGU_CLK_PLL;
> +
> +		if (caps) {
> +			pr_err("%s: PLL may not be combined with type 0x%x\n",
> +			       __func__, caps);
> +			goto out;
> +		}
> +	} else {
> +		clk_init.ops = &ingenic_clk_ops;
> +	}
> +
> +	/* nothing to do for gates or fixed dividers */
> +	caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV);
> +
> +	if (caps & CGU_CLK_MUX) {
> +		if (!(caps & CGU_CLK_MUX_GLITCHFREE))
> +			clk_init.flags |= CLK_SET_PARENT_GATE;
> +
> +		caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE);
> +	}
> +
> +	if (caps & CGU_CLK_DIV) {
> +		caps &= ~CGU_CLK_DIV;
> +	} else {
> +		/* pass rate changes to the parent clock */
> +		clk_init.flags |= CLK_SET_RATE_PARENT;
> +	}
> +
> +	if (caps) {
> +		pr_err("%s: unknown clock type 0x%x\n", __func__, caps);
> +		goto out;
> +	}
> +
> +	clk = clk_register(NULL, &ingenic_clk->hw);
> +	if (IS_ERR(clk)) {
> +		pr_err("%s: failed to register clock '%s'\n", __func__,
> +		       clk_info->name);
> +		err = PTR_ERR(clk);
> +		goto out;
> +	}
> +
> +	err = clk_register_clkdev(clk, clk_info->name, NULL);
> +	if (err)
> +		goto out;
> +
> +	cgu->clocks.clks[idx] = clk;
> +out:
> +	if (err)
> +		kfree(ingenic_clk);
> +	return err;
> +}
> +
> +struct ingenic_cgu *
> +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
> +		unsigned num_clocks, struct device_node *np)
> +{
> +	struct ingenic_cgu *cgu;
> +
> +	cgu = kzalloc(sizeof(*cgu), GFP_KERNEL);
> +	if (!cgu)
> +		goto err_out;
> +
> +	cgu->base = of_iomap(np, 0);
> +	if (!cgu->base) {
> +		pr_err("%s: failed to map CGU registers\n", __func__);
> +		goto err_out_free;
> +	}
> +
> +	cgu->np = np;
> +	cgu->clock_info = clock_info;
> +	cgu->clocks.clk_num = num_clocks;
> +
> +	spin_lock_init(&cgu->divmux_lock);
> +	spin_lock_init(&cgu->power_lock);
> +	spin_lock_init(&cgu->pll_lock);
> +
> +	return cgu;
> +
> +err_out_free:
> +	kfree(cgu);
> +err_out:
> +	return NULL;
> +}
> +
> +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu)
> +{
> +	unsigned i;
> +	int err;
> +
> +	cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *),
> +				   GFP_KERNEL);
> +	if (!cgu->clocks.clks) {
> +		err = -ENOMEM;
> +		goto err_out;
> +	}
> +
> +	for (i = 0; i < cgu->clocks.clk_num; i++) {
> +		err = register_clock(cgu, i);
> +		if (err)
> +			goto err_out_unregister;
> +	}
> +
> +	err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get,
> +				  &cgu->clocks);
> +	if (err)
> +		goto err_out_unregister;
> +
> +	return 0;
> +
> +err_out_unregister:
> +	if (cgu) {
> +		for (i = 0; i < cgu->clocks.clk_num; i++) {
> +			if (!cgu->clocks.clks[i])
> +				continue;
> +			if (cgu->clock_info[i].type & CGU_CLK_EXT)
> +				clk_put(cgu->clocks.clks[i]);
> +			else
> +				clk_unregister(cgu->clocks.clks[i]);
> +		}
> +		kfree(cgu->clocks.clks);
> +	}
> +err_out:
> +	return err;
> +}
> diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
> new file mode 100644
> index 0000000..47e0552
> --- /dev/null
> +++ b/drivers/clk/ingenic/cgu.h
> @@ -0,0 +1,223 @@
> +/*
> + * Ingenic SoC CGU driver
> + *
> + * Copyright (c) 2013-2015 Imagination Technologies
> + * Author: Paul Burton <paul.burton@imgtec.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __DRIVERS_CLK_INGENIC_CGU_H__
> +#define __DRIVERS_CLK_INGENIC_CGU_H__
> +
> +#include <linux/of.h>
> +#include <linux/spinlock.h>
> +
> +/**
> + * struct ingenic_cgu_pll_info - information about a PLL
> + * @reg: the offset of the PLL's control register within the CGU
> + * @m_shift: the number of bits to shift the multiplier value by (ie. the
> + *           index of the lowest bit of the multiplier value in the PLL's
> + *           control register)
> + * @m_bits: the size of the multiplier field in bits
> + * @m_offset: the multiplier value which encodes to 0 in the PLL's control
> + *            register
> + * @n_shift: the number of bits to shift the divider value by (ie. the
> + *           index of the lowest bit of the divider value in the PLL's
> + *           control register)
> + * @n_bits: the size of the divider field in bits
> + * @n_offset: the divider value which encodes to 0 in the PLL's control
> + *            register
> + * @od_shift: the number of bits to shift the post-VCO divider value by (ie.
> + *            the index of the lowest bit of the post-VCO divider value in
> + *            the PLL's control register)
> + * @od_bits: the size of the post-VCO divider field in bits
> + * @od_max: the maximum post-VCO divider value
> + * @od_encoding: a pointer to an array mapping post-VCO divider values to
> + *               their encoded values in the PLL control register, or -1 for
> + *               unsupported values
> + * @bypass_bit: the index of the bypass bit in the PLL control register
> + * @enable_bit: the index of the enable bit in the PLL control register
> + * @stable_bit: the index of the stable bit in the PLL control register
> + */
> +struct ingenic_cgu_pll_info {
> +	unsigned reg;
> +	unsigned m_shift, m_bits, m_offset;
> +	unsigned n_shift, n_bits, n_offset;
> +	unsigned od_shift, od_bits, od_max;
> +	const s8 *od_encoding;
> +	unsigned bypass_bit;
> +	unsigned enable_bit;
> +	unsigned stable_bit;
> +};
> +
> +/**
> + * struct ingenic_cgu_mux_info - information about a clock mux
> + * @reg: offset of the mux control register within the CGU
> + * @shift: number of bits to shift the mux value by (ie. the index of
> + *         the lowest bit of the mux value within its control register)
> + * @bits: the size of the mux value in bits
> + */
> +struct ingenic_cgu_mux_info {
> +	unsigned reg;
> +	unsigned shift:5;
> +	unsigned bits:5;
> +};
> +
> +/**
> + * struct ingenic_cgu_div_info - information about a divider
> + * @reg: offset of the divider control register within the CGU
> + * @shift: number of bits to shift the divide value by (ie. the index of
> + *         the lowest bit of the divide value within its control register)
> + * @bits: the size of the divide value in bits
> + * @ce_bit: the index of the change enable bit within reg, or -1 is there
> + *          isn't one
> + * @busy_bit: the index of the busy bit within reg, or -1 is there isn't one
> + * @stop_bit: the index of the stop bit within reg, or -1 is there isn't one
> + */
> +struct ingenic_cgu_div_info {
> +	unsigned reg;
> +	unsigned shift:5;
> +	unsigned bits:5;
> +	int ce_bit:6;
> +	int busy_bit:6;
> +	int stop_bit:6;
> +};
> +
> +/**
> + * struct ingenic_cgu_fixdiv_info - information about a fixed divider
> + * @div: the divider applied to the parent clock
> + */
> +struct ingenic_cgu_fixdiv_info {
> +	unsigned div;
> +};
> +
> +/**
> + * struct ingenic_cgu_gate_info - information about a clock gate
> + * @reg: offset of the gate control register within the CGU
> + * @bit: offset of the bit in the register that controls the gate
> + */
> +struct ingenic_cgu_gate_info {
> +	unsigned reg;
> +	unsigned bit:5;
> +};
> +
> +/**
> + * struct ingenic_cgu_custom_info - information about a custom (SoC) clock
> + */
> +struct ingenic_cgu_custom_info {
> +	struct clk_ops *clk_ops;
> +};
> +
> +/**
> + * struct ingenic_cgu_clk_info - information about a clock
> + * @name: name of the clock
> + * @type: a bitmask formed from CGU_CLK_* values
> + * @parents: an array of the indices of potential parents of this clock
> + *           within the clock_info array of the CGU, or -1 in entries
> + *           which correspond to no valid parent
> + * @pll: information valid if type includes CGU_CLK_PLL
> + * @gate: information valid if type includes CGU_CLK_GATE
> + * @mux: information valid if type includes CGU_CLK_MUX
> + * @div: information valid if type includes CGU_CLK_DIV
> + */
> +struct ingenic_cgu_clk_info {
> +	const char *name;
> +
> +	enum {
> +		CGU_CLK_NONE		= 0,
> +		CGU_CLK_EXT		= (1 << 0),
> +		CGU_CLK_PLL		= (1 << 1),
> +		CGU_CLK_GATE		= (1 << 2),
> +		CGU_CLK_MUX		= (1 << 3),
> +		CGU_CLK_MUX_GLITCHFREE	= (1 << 4),
> +		CGU_CLK_DIV		= (1 << 5),
> +		CGU_CLK_FIXDIV		= (1 << 6),
> +		CGU_CLK_CUSTOM		= (1 << 7),
> +	} type;
> +
> +	int parents[4];
> +
> +	union {
> +		struct ingenic_cgu_pll_info pll;
> +
> +		struct {
> +			struct ingenic_cgu_gate_info gate;
> +			struct ingenic_cgu_mux_info mux;
> +			struct ingenic_cgu_div_info div;
> +			struct ingenic_cgu_fixdiv_info fixdiv;
> +		};
> +
> +		struct ingenic_cgu_custom_info custom;
> +	};
> +};
> +
> +/**
> + * struct ingenic_cgu - data about the CGU
> + * @np: the device tree node that caused the CGU to be probed
> + * @base: the ioremap'ed base address of the CGU registers
> + * @clock_info: an array containing information about implemented clocks
> + * @clocks: used to provide clocks to DT, allows lookup of struct clk*
> + * @gate_lock: lock to be held whilst (un)gating a clock
> + * @divmux_lock: lock to be held whilst re-muxing of rate-changing a clock
> + */
> +struct ingenic_cgu {
> +	struct device_node *np;
> +	void __iomem *base;
> +
> +	const struct ingenic_cgu_clk_info *clock_info;
> +	struct clk_onecell_data clocks;
> +
> +	spinlock_t divmux_lock;		/* must be held when changing a divide
> +					   or re-muxing a clock */
> +	spinlock_t power_lock;		/* must be held when changing a power
> +					   manager register */
> +	spinlock_t pll_lock;		/* must be held when changing a PLL
> +					   control register */
> +};
> +
> +/**
> + * struct ingenic_clk - private data for a clock
> + * @hw: see Documentation/clk.txt
> + * @cgu: a pointer to the CGU data
> + * @idx: the index of this clock in cgu->clock_info
> + */
> +struct ingenic_clk {
> +	struct clk_hw hw;
> +	struct ingenic_cgu *cgu;
> +	unsigned idx;
> +};
> +
> +#define to_ingenic_clk(_hw) container_of(_hw, struct ingenic_clk, hw)
> +
> +/**
> + * ingenic_cgu_new - create a new CGU instance
> + * @clock_info: an array of clock information structures describing the clocks
> + *              which are implemented by the CGU
> + * @num_clocks: the number of entries in clock_info
> + * @np: the device tree node which causes this CGU to be probed
> + *
> + * Returns an opaque pointer to the CGU instance if initialisation & clock
> + * registration is successful, otherwise NULL.
> + */
> +struct ingenic_cgu *
> +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
> +		unsigned num_clocks, struct device_node *np);
> +
> +/**
> + * ingenic_cgu_register_clocks - Registers the clocks
> + * @cgu: pointer to cgu data
> + *
> + * Returns 1 on success and -EINVAL if unsuccesful.
> + */
> +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu);
> +
> +#endif /* __DRIVERS_CLK_INGENIC_CGU_H__ */
> -- 
> 2.3.5
> 
> 

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

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

* Re: [PATCH v3 25/37] clk: ingenic: add driver for Ingenic SoC CGU clocks
@ 2015-04-21 23:25     ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-21 23:25 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Mike Turquette

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

Hi Paul,

On Tue, Apr 21, 2015 at 03:46:52PM +0100, Paul Burton wrote:
> This driver supports the CGU clocks for Ingenic SoCs. It is generic
> enough to be usable across at least the JZ4740 to the JZ4780, and will
> be made use of on such devices in subsequent commits. This patch by
> itself only adds the SoC-agnostic infrastructure that forms the bulk of
> the CGU driver for the aforementioned further commits to make use of.
> 
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Co-authored-by: Paul Cercueil <paul@crapouillou.net>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Cc: Mike Turquette <mturquette@linaro.org>
> ---
> Changes in v3:
>   - s/jz47xx/ingenic/ since Ingenic have changed their naming scheme to
>     "Mxxx" for newer SoCs.
> 
>   - Allow clock gating with registers other than CLKGR* (pcercuei).
> 
>   - Fixup dividers to never exceed the requested rate (pcercuei).
> 
>   - Fixup PLL calculations to work better with more restricted
>     coefficient bit widths (pcercuei).
> 
> Changes in v2:
>   - Fix spinlock handling in jz47xx_clk_set_rate error path (ZubairLK).
> ---
>  drivers/clk/Makefile         |   1 +
>  drivers/clk/ingenic/Makefile |   1 +
>  drivers/clk/ingenic/cgu.c    | 711 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/ingenic/cgu.h    | 223 ++++++++++++++
>  4 files changed, 936 insertions(+)
>  create mode 100644 drivers/clk/ingenic/Makefile
>  create mode 100644 drivers/clk/ingenic/cgu.c
>  create mode 100644 drivers/clk/ingenic/cgu.h
> 
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 3d00c25..cc77327 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -50,6 +50,7 @@ obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
>  obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
>  obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
>  obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
> +obj-$(CONFIG_MACH_INGENIC)		+= ingenic/
>  obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
>  ifeq ($(CONFIG_COMMON_CLK), y)
>  obj-$(CONFIG_ARCH_MMP)			+= mmp/
> diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
> new file mode 100644
> index 0000000..5ac2fd9
> --- /dev/null
> +++ b/drivers/clk/ingenic/Makefile
> @@ -0,0 +1 @@
> +obj-y				+= cgu.o
> diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
> new file mode 100644
> index 0000000..81a720e
> --- /dev/null
> +++ b/drivers/clk/ingenic/cgu.c
> @@ -0,0 +1,713 @@
> +/*
> + * Ingenic SoC CGU driver
> + *
> + * Copyright (c) 2013-2015 Imagination Technologies
> + * Author: Paul Burton <paul.burton@imgtec.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include "cgu.h"
> +
> +#define MHZ (1000 * 1000)
> +
> +/**
> + * ingenic_cgu_gate_get - get the value of clock gate register bit

I think you should have "()" in there because its a function (if
Documentation/kernel-doc-nano-HOWTO.txt is anything to go by).

> + * @cgu: reference to the CGU whose registers should be read
> + * @idx: index of the gate bit

Stale

> + *
> + * Returns 1 if the gate bit is set, else 0. The index begins with 0 being

I believe its common for return value to have its own section at the
end, which shows up nicer in the output, e.g.

 * The index begins with 0 being bit 0 of CLKGR0, continuing from 32 for
 * bit 0 of CLKGR1 etc. For example, the index of bit 9 of CLKGR1 would
 * be (32+9) == 41.
 *
 * The caller must hold cgu->power_lock.
 *
 * Return: 1 if the gate bit is set, else 0.

> + * bit 0 of CLKGR0, continuing from 32 for bit 0 of CLKGR1 etc. For example,
> + * the index of bit 9 of CLKGR1 would be (32+9) == 41.

I'm guessing that's a bit stale too.

> + *
> + * The caller must hold cgu->power_lock.
> + */
> +static inline unsigned

maybe return bool and scrap the !!(

> +ingenic_cgu_gate_get(struct ingenic_cgu *cgu,
> +		     const struct ingenic_cgu_gate_info *info)
> +{
> +	return !!(readl(cgu->base + info->reg) & BIT(info->bit));
> +}
> +
> +/**
> + * ingenic_cgu_gate_set - set the value of clock gate register bit
> + * @cgu: reference to the CGU whose registers should be modified
> + * @idx: index of the gate bit
> + * @val: non-zero to gate a clock, otherwise zero
> + *
> + * Sets the given gate bit in order to gate or ungate a clock. See
> + * ingenic_cgu_gate_get for a description of the idx parameter.
> + *
> + * The caller must hold cgu->power_lock.
> + */

same as above

> +static inline void
> +ingenic_cgu_gate_set(struct ingenic_cgu *cgu,
> +		     const struct ingenic_cgu_gate_info *info, bool val)
> +{
> +	u32 clkgr = readl(cgu->base + info->reg);
> +
> +	if (val)
> +		clkgr |= BIT(info->bit);

Don't forget
#include <linux/bitops.h>
for BIT() and GENMASK()

> +	else
> +		clkgr &= ~BIT(info->bit);
> +
> +	writel(clkgr, cgu->base + info->reg);
> +}
> +
> +/*
> + * PLL operations
> + */
> +
> +static unsigned long
> +ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	const struct ingenic_cgu_pll_info *pll_info;
> +	unsigned m, n, od_enc, od;
> +	bool bypass, enable;
> +	unsigned long flags;
> +	u32 ctl;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +	BUG_ON(clk_info->type != CGU_CLK_PLL);
> +	pll_info = &clk_info->pll;
> +
> +	spin_lock_irqsave(&cgu->pll_lock, flags);
> +	ctl = readl(cgu->base + pll_info->reg);
> +	spin_unlock_irqrestore(&cgu->pll_lock, flags);
> +
> +	m = ((ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0));
> +	m += pll_info->m_offset;
> +	n = ((ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0));
> +	n += pll_info->n_offset;
> +	od_enc = ctl >> pll_info->od_shift;
> +	od_enc &= GENMASK(pll_info->od_bits - 1, 0);
> +	bypass = !!(ctl & BIT(pll_info->bypass_bit));
> +	enable = !!(ctl & BIT(pll_info->enable_bit));
> +
> +	if (bypass)
> +		return parent_rate;
> +
> +	if (!enable)
> +		return 0;
> +
> +	for (od = 0; od < pll_info->od_max; od++) {
> +		if (pll_info->od_encoding[od] == od_enc)
> +			break;
> +	}
> +	BUG_ON(od == pll_info->od_max);
> +	od++;
> +
> +	return parent_rate * m / (n * od);

In the worst case for jz4740 looking a couple of patches ahead, raw m
can be as high as 0x1ff, offset to 0x201 = 513. That means parent_rate
must be < 8.37MHz to avoid overflow. TZ1090 PLL (which looks
conceptually similar) does this:

f_out = div_u64((u64)f_in * clk_f,
		2 * clk_r * clk_od);

https://lkml.org/lkml/2014/12/1/832

> +}
> +
> +static unsigned long
> +ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
> +		 unsigned long rate, unsigned long parent_rate,
> +		 unsigned *pm, unsigned *pn, unsigned *pod)
> +{
> +	unsigned m, n, od;
> +
> +	od = 1;
> +
> +	/*
> +	 * The frequency after the input divider must be between 10 and 50 MHz.
> +	 * The highest divider yields the best resolution.
> +	 */
> +	n = parent_rate / (10 * MHZ);
> +	n = min_t(unsigned, n, 1 << clk_info->pll.n_bits);
> +	n = max_t(unsigned, n, 1);
> +
> +	m = (rate / MHZ) * od * n / (parent_rate / MHZ);
> +	m = min_t(unsigned, m, 1 << clk_info->pll.m_bits);
> +	m = max_t(unsigned, m, 1);

These appear to assume m_offset & n_offset are both 1.

> +
> +	if (pm)
> +		*pm = m;
> +	if (pn)
> +		*pn = n;
> +	if (pod)
> +		*pod = od;
> +
> +	return parent_rate * m / (n * od);

same again


You may want to consider a more brute force approach like TZ1090 does at
some point, for maximum accuracy and to avoid problems when output is
fed back in as input and gives a different result:

rate = clk_round_rate(clk, desired);
clk_set_rate(clk, rate);
actual_rate = clk_get_rate(clk);

rate != actual_rate

I can't tell from a superficial glance whether its vulnerable to that
problem.

> +}
> +
> +static long
> +ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
> +		       unsigned long *prate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +	BUG_ON(clk_info->type != CGU_CLK_PLL);
> +
> +	return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
> +}
> +
> +static int
> +ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
> +		     unsigned long parent_rate)
> +{
> +	const unsigned timeout = 100;
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	const struct ingenic_cgu_pll_info *pll_info;
> +	unsigned long rate, flags;
> +	unsigned m, n, od, i;
> +	u32 ctl;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +	BUG_ON(clk_info->type != CGU_CLK_PLL);
> +	pll_info = &clk_info->pll;
> +
> +	rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
> +			       &m, &n, &od);
> +	if (rate != req_rate)
> +		pr_info("ingenic-cgu: request '%s' rate %luHz, actual %luHz\n",
> +			clk_info->name, req_rate, rate);
> +
> +	spin_lock_irqsave(&cgu->pll_lock, flags);
> +	ctl = readl(cgu->base + pll_info->reg);
> +
> +	ctl &= ~(GENMASK(pll_info->m_bits - 1, 0) << pll_info->m_shift);
> +	ctl |= (m - pll_info->m_offset) << pll_info->m_shift;
> +
> +	ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift);
> +	ctl |= (n - pll_info->n_offset) << pll_info->n_shift;
> +
> +	ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
> +	ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
> +
> +	ctl &= ~BIT(pll_info->bypass_bit);
> +	ctl |= BIT(pll_info->enable_bit);
> +
> +	writel(ctl, cgu->base + pll_info->reg);
> +
> +	/* wait for the PLL to stabilise */
> +	for (i = 0; i < timeout; i++) {
> +		ctl = readl(cgu->base + pll_info->reg);
> +		if (ctl & BIT(pll_info->stable_bit))
> +			break;
> +		mdelay(1);
> +	}
> +
> +	spin_unlock_irqrestore(&cgu->pll_lock, flags);
> +
> +	if (i == timeout)
> +		return -EBUSY;
> +
> +	return 0;
> +}
> +
> +static const struct clk_ops ingenic_pll_ops = {
> +	.recalc_rate = ingenic_pll_recalc_rate,
> +	.round_rate = ingenic_pll_round_rate,
> +	.set_rate = ingenic_pll_set_rate,
> +};
> +
> +/*
> + * Operations for all non-PLL clocks
> + */
> +
> +static u8 ingenic_clk_get_parent(struct clk_hw *hw)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	u32 reg;
> +	u8 i, hw_idx, idx = 0;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_MUX) {
> +		reg = readl(cgu->base + clk_info->mux.reg);
> +		hw_idx = (reg >> clk_info->mux.shift) &
> +			 ((1 << clk_info->mux.bits) - 1);

Looks like a good place for GENMASK like elsewhere. Maybe same in a few
places below.

> +
> +		/*
> +		 * Convert the hardware index to the parent index by skipping
> +		 * over any -1's in the parents array.
> +		 */
> +		for (i = 0; i < hw_idx; i++) {
> +			if (clk_info->parents[i] != -1)
> +				idx++;
> +		}
> +	}
> +
> +	return idx;
> +}
> +
> +static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long flags;
> +	u8 curr_idx, hw_idx, num_poss;
> +	u32 reg, mask;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_MUX) {
> +		/*
> +		 * Convert the parent index to the hardware index by adding
> +		 * 1 for any -1 in the parents array preceding the given
> +		 * index. That is, we want the index of idx'th entry in
> +		 * clk_info->parents which does not equal -1.
> +		 */
> +		hw_idx = curr_idx = 0;
> +		num_poss = 1 << clk_info->mux.bits;
> +		for (; (hw_idx < num_poss) && (curr_idx != idx); hw_idx++) {

if idx==0, this'll never iterate since curr_idx starts at 0, even if the
first parent is -1. It's basically an off-by-one error I think.

> +			if (clk_info->parents[hw_idx] == -1)
> +				continue;
> +			curr_idx++;

maybe move the curr_idx == idx check here.

> +		}
> +
> +		/* idx should always be a valid parent */
> +		BUG_ON(curr_idx != idx);

Hmm, i suppose. BUG_ON(hw_idx == num_poss) looks more direct/intuitive
to me, but probably subjective.

> +
> +		mask = ((1 << clk_info->mux.bits) - 1) << clk_info->mux.shift;
> +
> +		spin_lock_irqsave(&cgu->divmux_lock, flags);
> +
> +		/* write the register */
> +		reg = readl(cgu->base + clk_info->mux.reg);
> +		reg &= ~mask;
> +		reg |= hw_idx << clk_info->mux.shift;
> +		writel(reg, cgu->base + clk_info->mux.reg);
> +
> +		spin_unlock_irqrestore(&cgu->divmux_lock, flags);
> +		return 0;
> +	}
> +
> +	return idx ? -EINVAL : 0;
> +}
> +
> +static unsigned long
> +ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long rate = parent_rate;
> +	u32 div_reg, div;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_DIV) {
> +		div_reg = readl(cgu->base + clk_info->div.reg);
> +		div = (div_reg >> clk_info->div.shift) &
> +		      ((1 << clk_info->div.bits) - 1);
> +		div += 1;
> +
> +		rate /= div;
> +	}
> +
> +	return rate;
> +}
> +
> +static unsigned
> +ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info,
> +		     unsigned long parent_rate, unsigned long req_rate)
> +{
> +	unsigned div;
> +
> +	/* calculate the divide */
> +	div = DIV_ROUND_UP(parent_rate, req_rate);
> +
> +	/* and impose hardware constraints */
> +	div = min_t(unsigned, div, 1 << clk_info->div.bits);
> +	div = max_t(unsigned, div, 1);
> +
> +	return div;
> +}
> +
> +static long
> +ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
> +		       unsigned long *parent_rate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	long rate = req_rate;

should the default be *parent_rate?

> +	unsigned div;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_DIV) {
> +		div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
> +		rate = *parent_rate / div;
> +	} else if (clk_info->type & CGU_CLK_FIXDIV) {
> +		rate = *parent_rate / clk_info->fixdiv.div;
> +	}
> +
> +	return rate;
> +}
> +
> +static int
> +ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
> +		     unsigned long parent_rate)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	const unsigned timeout = 100;
> +	unsigned long rate, flags;
> +	unsigned div, i;
> +	u32 reg, mask;
> +	int ret = 0;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_DIV) {
> +		div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate);
> +		rate = parent_rate / div;
> +
> +		if (rate != req_rate)
> +			return -EINVAL;
> +
> +		spin_lock_irqsave(&cgu->divmux_lock, flags);
> +		reg = readl(cgu->base + clk_info->div.reg);
> +
> +		/* update the divide */
> +		mask = (1 << clk_info->div.bits) - 1;
> +		reg &= ~(mask << clk_info->div.shift);
> +		reg |= (div - 1) << clk_info->div.shift;
> +
> +		/* clear the stop bit */
> +		if (clk_info->div.stop_bit != -1)
> +			reg &= ~(1 << clk_info->div.stop_bit);

BIT() (same for a couple of cases below)

> +
> +		/* set the change enable bit */
> +		if (clk_info->div.ce_bit != -1)
> +			reg |= 1 << clk_info->div.ce_bit;
> +
> +		/* update the hardware */
> +		writel(reg, cgu->base + clk_info->div.reg);
> +
> +		/* wait for the change to take effect */
> +		if (clk_info->div.busy_bit != -1) {
> +			for (i = 0; i < timeout; i++) {
> +				reg = readl(cgu->base + clk_info->div.reg);
> +				if (!(reg & (1 << clk_info->div.busy_bit)))
> +					break;
> +				mdelay(1);
> +			}
> +			if (i == timeout)
> +				ret = -EBUSY;
> +		}
> +
> +		spin_unlock_irqrestore(&cgu->divmux_lock, flags);

Is the main common clk lock & mutex insufficient? Setting rate appears
to take a mutex anyway, so you're already not in atomic context, in
which case maybe s/mdelay/msleep/ throughout if you can get rid of the
locks.

Its getting late. I'll continue looking at this patch some other time.

Cheers
James

> +		return ret;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int ingenic_clk_enable(struct clk_hw *hw)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long flags;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_GATE) {
> +		/* ungate the clock */
> +		spin_lock_irqsave(&cgu->power_lock, flags);
> +		ingenic_cgu_gate_set(cgu, &clk_info->gate, false);
> +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> +	}
> +
> +	return 0;
> +}
> +
> +static void ingenic_clk_disable(struct clk_hw *hw)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long flags;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_GATE) {
> +		/* gate the clock */
> +		spin_lock_irqsave(&cgu->power_lock, flags);
> +		ingenic_cgu_gate_set(cgu, &clk_info->gate, true);
> +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> +	}
> +}
> +
> +static int ingenic_clk_is_enabled(struct clk_hw *hw)
> +{
> +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> +	const struct ingenic_cgu_clk_info *clk_info;
> +	unsigned long flags;
> +	int enabled = 1;
> +
> +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> +
> +	if (clk_info->type & CGU_CLK_GATE) {
> +		spin_lock_irqsave(&cgu->power_lock, flags);
> +		enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
> +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> +	}
> +
> +	return enabled;
> +}
> +
> +static const struct clk_ops ingenic_clk_ops = {
> +	.get_parent = ingenic_clk_get_parent,
> +	.set_parent = ingenic_clk_set_parent,
> +
> +	.recalc_rate = ingenic_clk_recalc_rate,
> +	.round_rate = ingenic_clk_round_rate,
> +	.set_rate = ingenic_clk_set_rate,
> +
> +	.enable = ingenic_clk_enable,
> +	.disable = ingenic_clk_disable,
> +	.is_enabled = ingenic_clk_is_enabled,
> +};
> +
> +/*
> + * Setup functions.
> + */
> +
> +static int register_clock(struct ingenic_cgu *cgu, unsigned idx)
> +{
> +	const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx];
> +	struct clk_init_data clk_init;
> +	struct ingenic_clk *ingenic_clk = NULL;
> +	struct clk *clk, *parent;
> +	const char *parent_names[4];
> +	unsigned caps, i, num_possible;
> +	int err = -EINVAL;
> +
> +	BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names));
> +
> +	if (clk_info->type == CGU_CLK_EXT) {
> +		clk = of_clk_get_by_name(cgu->np, clk_info->name);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: no external clock '%s' provided\n",
> +			       __func__, clk_info->name);
> +			err = -ENODEV;
> +			goto out;
> +		}
> +		err = clk_register_clkdev(clk, clk_info->name, NULL);
> +		if (err) {
> +			clk_put(clk);
> +			goto out;
> +		}
> +		cgu->clocks.clks[idx] = clk;
> +		return 0;
> +	}
> +
> +	if (!clk_info->type) {
> +		pr_err("%s: no clock type specified for '%s'\n", __func__,
> +		       clk_info->name);
> +		goto out;
> +	}
> +
> +	ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL);
> +	if (!ingenic_clk) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +
> +	ingenic_clk->hw.init = &clk_init;
> +	ingenic_clk->cgu = cgu;
> +	ingenic_clk->idx = idx;
> +
> +	clk_init.name = clk_info->name;
> +	clk_init.flags = 0;
> +	clk_init.parent_names = parent_names;
> +
> +	caps = clk_info->type;
> +
> +	if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
> +		clk_init.num_parents = 0;
> +
> +		if (caps & CGU_CLK_MUX)
> +			num_possible = 1 << clk_info->mux.bits;
> +		else
> +			num_possible = ARRAY_SIZE(clk_info->parents);
> +
> +		for (i = 0; i < num_possible; i++) {
> +			if (clk_info->parents[i] == -1)
> +				continue;
> +
> +			parent = cgu->clocks.clks[clk_info->parents[i]];
> +			parent_names[clk_init.num_parents] =
> +				__clk_get_name(parent);
> +			clk_init.num_parents++;
> +		}
> +
> +		BUG_ON(!clk_init.num_parents);
> +		BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names));
> +	} else {
> +		BUG_ON(clk_info->parents[0] == -1);
> +		clk_init.num_parents = 1;
> +		parent = cgu->clocks.clks[clk_info->parents[0]];
> +		parent_names[0] = __clk_get_name(parent);
> +	}
> +
> +	if (caps & CGU_CLK_CUSTOM) {
> +		clk_init.ops = clk_info->custom.clk_ops;
> +
> +		caps &= ~CGU_CLK_CUSTOM;
> +
> +		if (caps) {
> +			pr_err("%s: custom clock may not be combined with type 0x%x\n",
> +			       __func__, caps);
> +			goto out;
> +		}
> +	} else if (caps & CGU_CLK_PLL) {
> +		clk_init.ops = &ingenic_pll_ops;
> +
> +		caps &= ~CGU_CLK_PLL;
> +
> +		if (caps) {
> +			pr_err("%s: PLL may not be combined with type 0x%x\n",
> +			       __func__, caps);
> +			goto out;
> +		}
> +	} else {
> +		clk_init.ops = &ingenic_clk_ops;
> +	}
> +
> +	/* nothing to do for gates or fixed dividers */
> +	caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV);
> +
> +	if (caps & CGU_CLK_MUX) {
> +		if (!(caps & CGU_CLK_MUX_GLITCHFREE))
> +			clk_init.flags |= CLK_SET_PARENT_GATE;
> +
> +		caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE);
> +	}
> +
> +	if (caps & CGU_CLK_DIV) {
> +		caps &= ~CGU_CLK_DIV;
> +	} else {
> +		/* pass rate changes to the parent clock */
> +		clk_init.flags |= CLK_SET_RATE_PARENT;
> +	}
> +
> +	if (caps) {
> +		pr_err("%s: unknown clock type 0x%x\n", __func__, caps);
> +		goto out;
> +	}
> +
> +	clk = clk_register(NULL, &ingenic_clk->hw);
> +	if (IS_ERR(clk)) {
> +		pr_err("%s: failed to register clock '%s'\n", __func__,
> +		       clk_info->name);
> +		err = PTR_ERR(clk);
> +		goto out;
> +	}
> +
> +	err = clk_register_clkdev(clk, clk_info->name, NULL);
> +	if (err)
> +		goto out;
> +
> +	cgu->clocks.clks[idx] = clk;
> +out:
> +	if (err)
> +		kfree(ingenic_clk);
> +	return err;
> +}
> +
> +struct ingenic_cgu *
> +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
> +		unsigned num_clocks, struct device_node *np)
> +{
> +	struct ingenic_cgu *cgu;
> +
> +	cgu = kzalloc(sizeof(*cgu), GFP_KERNEL);
> +	if (!cgu)
> +		goto err_out;
> +
> +	cgu->base = of_iomap(np, 0);
> +	if (!cgu->base) {
> +		pr_err("%s: failed to map CGU registers\n", __func__);
> +		goto err_out_free;
> +	}
> +
> +	cgu->np = np;
> +	cgu->clock_info = clock_info;
> +	cgu->clocks.clk_num = num_clocks;
> +
> +	spin_lock_init(&cgu->divmux_lock);
> +	spin_lock_init(&cgu->power_lock);
> +	spin_lock_init(&cgu->pll_lock);
> +
> +	return cgu;
> +
> +err_out_free:
> +	kfree(cgu);
> +err_out:
> +	return NULL;
> +}
> +
> +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu)
> +{
> +	unsigned i;
> +	int err;
> +
> +	cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *),
> +				   GFP_KERNEL);
> +	if (!cgu->clocks.clks) {
> +		err = -ENOMEM;
> +		goto err_out;
> +	}
> +
> +	for (i = 0; i < cgu->clocks.clk_num; i++) {
> +		err = register_clock(cgu, i);
> +		if (err)
> +			goto err_out_unregister;
> +	}
> +
> +	err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get,
> +				  &cgu->clocks);
> +	if (err)
> +		goto err_out_unregister;
> +
> +	return 0;
> +
> +err_out_unregister:
> +	if (cgu) {
> +		for (i = 0; i < cgu->clocks.clk_num; i++) {
> +			if (!cgu->clocks.clks[i])
> +				continue;
> +			if (cgu->clock_info[i].type & CGU_CLK_EXT)
> +				clk_put(cgu->clocks.clks[i]);
> +			else
> +				clk_unregister(cgu->clocks.clks[i]);
> +		}
> +		kfree(cgu->clocks.clks);
> +	}
> +err_out:
> +	return err;
> +}
> diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
> new file mode 100644
> index 0000000..47e0552
> --- /dev/null
> +++ b/drivers/clk/ingenic/cgu.h
> @@ -0,0 +1,223 @@
> +/*
> + * Ingenic SoC CGU driver
> + *
> + * Copyright (c) 2013-2015 Imagination Technologies
> + * Author: Paul Burton <paul.burton@imgtec.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __DRIVERS_CLK_INGENIC_CGU_H__
> +#define __DRIVERS_CLK_INGENIC_CGU_H__
> +
> +#include <linux/of.h>
> +#include <linux/spinlock.h>
> +
> +/**
> + * struct ingenic_cgu_pll_info - information about a PLL
> + * @reg: the offset of the PLL's control register within the CGU
> + * @m_shift: the number of bits to shift the multiplier value by (ie. the
> + *           index of the lowest bit of the multiplier value in the PLL's
> + *           control register)
> + * @m_bits: the size of the multiplier field in bits
> + * @m_offset: the multiplier value which encodes to 0 in the PLL's control
> + *            register
> + * @n_shift: the number of bits to shift the divider value by (ie. the
> + *           index of the lowest bit of the divider value in the PLL's
> + *           control register)
> + * @n_bits: the size of the divider field in bits
> + * @n_offset: the divider value which encodes to 0 in the PLL's control
> + *            register
> + * @od_shift: the number of bits to shift the post-VCO divider value by (ie.
> + *            the index of the lowest bit of the post-VCO divider value in
> + *            the PLL's control register)
> + * @od_bits: the size of the post-VCO divider field in bits
> + * @od_max: the maximum post-VCO divider value
> + * @od_encoding: a pointer to an array mapping post-VCO divider values to
> + *               their encoded values in the PLL control register, or -1 for
> + *               unsupported values
> + * @bypass_bit: the index of the bypass bit in the PLL control register
> + * @enable_bit: the index of the enable bit in the PLL control register
> + * @stable_bit: the index of the stable bit in the PLL control register
> + */
> +struct ingenic_cgu_pll_info {
> +	unsigned reg;
> +	unsigned m_shift, m_bits, m_offset;
> +	unsigned n_shift, n_bits, n_offset;
> +	unsigned od_shift, od_bits, od_max;
> +	const s8 *od_encoding;
> +	unsigned bypass_bit;
> +	unsigned enable_bit;
> +	unsigned stable_bit;
> +};
> +
> +/**
> + * struct ingenic_cgu_mux_info - information about a clock mux
> + * @reg: offset of the mux control register within the CGU
> + * @shift: number of bits to shift the mux value by (ie. the index of
> + *         the lowest bit of the mux value within its control register)
> + * @bits: the size of the mux value in bits
> + */
> +struct ingenic_cgu_mux_info {
> +	unsigned reg;
> +	unsigned shift:5;
> +	unsigned bits:5;
> +};
> +
> +/**
> + * struct ingenic_cgu_div_info - information about a divider
> + * @reg: offset of the divider control register within the CGU
> + * @shift: number of bits to shift the divide value by (ie. the index of
> + *         the lowest bit of the divide value within its control register)
> + * @bits: the size of the divide value in bits
> + * @ce_bit: the index of the change enable bit within reg, or -1 is there
> + *          isn't one
> + * @busy_bit: the index of the busy bit within reg, or -1 is there isn't one
> + * @stop_bit: the index of the stop bit within reg, or -1 is there isn't one
> + */
> +struct ingenic_cgu_div_info {
> +	unsigned reg;
> +	unsigned shift:5;
> +	unsigned bits:5;
> +	int ce_bit:6;
> +	int busy_bit:6;
> +	int stop_bit:6;
> +};
> +
> +/**
> + * struct ingenic_cgu_fixdiv_info - information about a fixed divider
> + * @div: the divider applied to the parent clock
> + */
> +struct ingenic_cgu_fixdiv_info {
> +	unsigned div;
> +};
> +
> +/**
> + * struct ingenic_cgu_gate_info - information about a clock gate
> + * @reg: offset of the gate control register within the CGU
> + * @bit: offset of the bit in the register that controls the gate
> + */
> +struct ingenic_cgu_gate_info {
> +	unsigned reg;
> +	unsigned bit:5;
> +};
> +
> +/**
> + * struct ingenic_cgu_custom_info - information about a custom (SoC) clock
> + */
> +struct ingenic_cgu_custom_info {
> +	struct clk_ops *clk_ops;
> +};
> +
> +/**
> + * struct ingenic_cgu_clk_info - information about a clock
> + * @name: name of the clock
> + * @type: a bitmask formed from CGU_CLK_* values
> + * @parents: an array of the indices of potential parents of this clock
> + *           within the clock_info array of the CGU, or -1 in entries
> + *           which correspond to no valid parent
> + * @pll: information valid if type includes CGU_CLK_PLL
> + * @gate: information valid if type includes CGU_CLK_GATE
> + * @mux: information valid if type includes CGU_CLK_MUX
> + * @div: information valid if type includes CGU_CLK_DIV
> + */
> +struct ingenic_cgu_clk_info {
> +	const char *name;
> +
> +	enum {
> +		CGU_CLK_NONE		= 0,
> +		CGU_CLK_EXT		= (1 << 0),
> +		CGU_CLK_PLL		= (1 << 1),
> +		CGU_CLK_GATE		= (1 << 2),
> +		CGU_CLK_MUX		= (1 << 3),
> +		CGU_CLK_MUX_GLITCHFREE	= (1 << 4),
> +		CGU_CLK_DIV		= (1 << 5),
> +		CGU_CLK_FIXDIV		= (1 << 6),
> +		CGU_CLK_CUSTOM		= (1 << 7),
> +	} type;
> +
> +	int parents[4];
> +
> +	union {
> +		struct ingenic_cgu_pll_info pll;
> +
> +		struct {
> +			struct ingenic_cgu_gate_info gate;
> +			struct ingenic_cgu_mux_info mux;
> +			struct ingenic_cgu_div_info div;
> +			struct ingenic_cgu_fixdiv_info fixdiv;
> +		};
> +
> +		struct ingenic_cgu_custom_info custom;
> +	};
> +};
> +
> +/**
> + * struct ingenic_cgu - data about the CGU
> + * @np: the device tree node that caused the CGU to be probed
> + * @base: the ioremap'ed base address of the CGU registers
> + * @clock_info: an array containing information about implemented clocks
> + * @clocks: used to provide clocks to DT, allows lookup of struct clk*
> + * @gate_lock: lock to be held whilst (un)gating a clock
> + * @divmux_lock: lock to be held whilst re-muxing of rate-changing a clock
> + */
> +struct ingenic_cgu {
> +	struct device_node *np;
> +	void __iomem *base;
> +
> +	const struct ingenic_cgu_clk_info *clock_info;
> +	struct clk_onecell_data clocks;
> +
> +	spinlock_t divmux_lock;		/* must be held when changing a divide
> +					   or re-muxing a clock */
> +	spinlock_t power_lock;		/* must be held when changing a power
> +					   manager register */
> +	spinlock_t pll_lock;		/* must be held when changing a PLL
> +					   control register */
> +};
> +
> +/**
> + * struct ingenic_clk - private data for a clock
> + * @hw: see Documentation/clk.txt
> + * @cgu: a pointer to the CGU data
> + * @idx: the index of this clock in cgu->clock_info
> + */
> +struct ingenic_clk {
> +	struct clk_hw hw;
> +	struct ingenic_cgu *cgu;
> +	unsigned idx;
> +};
> +
> +#define to_ingenic_clk(_hw) container_of(_hw, struct ingenic_clk, hw)
> +
> +/**
> + * ingenic_cgu_new - create a new CGU instance
> + * @clock_info: an array of clock information structures describing the clocks
> + *              which are implemented by the CGU
> + * @num_clocks: the number of entries in clock_info
> + * @np: the device tree node which causes this CGU to be probed
> + *
> + * Returns an opaque pointer to the CGU instance if initialisation & clock
> + * registration is successful, otherwise NULL.
> + */
> +struct ingenic_cgu *
> +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
> +		unsigned num_clocks, struct device_node *np);
> +
> +/**
> + * ingenic_cgu_register_clocks - Registers the clocks
> + * @cgu: pointer to cgu data
> + *
> + * Returns 1 on success and -EINVAL if unsuccesful.
> + */
> +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu);
> +
> +#endif /* __DRIVERS_CLK_INGENIC_CGU_H__ */
> -- 
> 2.3.5
> 
> 

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

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

* Re: [PATCH v3 00/37] JZ4780 & CI20 support
  2015-04-21 14:46 ` Paul Burton
@ 2015-04-22  4:06     ` Rob Herring
  -1 siblings, 0 replies; 102+ messages in thread
From: Rob Herring @ 2015-04-22  4:06 UTC (permalink / raw)
  To: Paul Burton
  Cc: Linux-MIPS, Lars-Peter Clausen, Paul Cercueil, Thomas Gleixner,
	Jason Cooper, Mike Turquette, Greg Kroah-Hartman,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA

On Tue, Apr 21, 2015 at 9:46 AM, Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org> wrote:
> This series introduces initial support for the Ingenic JZ4780 SoC and
> the Imagination Technologies MIPS Creator CI20 board which is built
> around it. In the process the existing JZ4740 & qi_lb60 code gains
> initial support for using DeviceTree such that much of the existing
> platform code under arch/mips/jz4740 can be shared.
>
> The series has undergone quite a bit of restructure since v2. Each
> patch contains a changelog indicating its differences, but a rough
> overview for changes across the series would be:
>
>   - s/jz47xx/ingenic/ in various places, to reflect the fact that
>     Ingenic have changed the naming scheme for their newest SoCs
>     (now Mxxx).
>
>   - Restructure the Kconfig entries to provide a MACH_INGENIC
>     indicating and Ingenic SoC, and have boards select the
>     appropriate SoC symbol.
>
>   - Merge DT binding documentation where SoC bindings differ only
>     by compatible strings.
>
>   - Capitalise "JZ" in SoC names, where not identifiers in code,
>     to match the way Ingenic write them.
>
>   - Further clean up the Ingenic SoC interrupt controller driver
>     and move it under drivers/irqchip/.
>
> Review appreciated, and hopefully this can make it into v4.2.
>
> Thanks,
>     Paul
>
> Paul Burton (37):
>   devicetree/bindings: add Ingenic Semiconductor vendor prefix
>   devicetree/bindings: add Qi Hardware vendor prefix
>   MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
>   MIPS: ingenic: add newer vendor IDs
>   MIPS: JZ4740: require & include DT
>   MIPS: irq_cpu: declare irqchip table entry
>   MIPS: JZ4740: probe CPU interrupt controller via DT
>   MIPS: JZ4740: use generic plat_irq_dispatch
>   MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
>   devicetree: document Ingenic SoC interrupt controller binding

For patches 1, 2, and 10:

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

>   MIPS: JZ4740: probe interrupt controller via DT
>   MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
>   MIPS: JZ4740: register an irq_domain for the interrupt controller
>   MIPS: JZ4740: drop intc debugfs code
>   MIPS: JZ4740: remove jz_intc_base global
>   MIPS: JZ4740: support >32 interrupts
>   MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
>   MIPS: JZ4740: read intc base address from DT
>   MIPS: JZ4740: avoid JZ4740-specific naming
>   MIPS: JZ4740: support newer SoC interrupt controllers
>   irqchip: move Ingenic SoC intc driver to drivers/irqchip
>   MIPS: JZ4740: call jz4740_clock_init earlier
>   MIPS: JZ4740: replace use of jz4740_clock_bdata
>   devicetree: add Ingenic CGU binding documentation
>   clk: ingenic: add driver for Ingenic SoC CGU clocks
>   MIPS,clk: migrate JZ4740 to common clock framework
>   MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
>   MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
>   MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
>   clk: ingenic: add JZ4780 CGU support
>   MIPS: JZ4740: remove clock.h
>   MIPS: JZ4740: only detect RAM size if not specified in DT
>   devicetree: document Ingenic SoC UART binding
>   serial: 8250_ingenic: support for Ingenic SoC UARTs
>   MIPS: JZ4740: use Ingenic SoC UART driver
>   MIPS: ingenic: initial JZ4780 support
>   MIPS: ingenic: initial MIPS Creator CI20 support
>
>  .../devicetree/bindings/clock/ingenic,cgu.txt      |  53 ++
>  .../bindings/interrupt-controller/ingenic,intc.txt |  25 +
>  .../devicetree/bindings/serial/ingenic,uart.txt    |  22 +
>  .../devicetree/bindings/vendor-prefixes.txt        |   2 +
>  arch/mips/Kconfig                                  |  11 +-
>  arch/mips/boot/dts/Makefile                        |   1 +
>  arch/mips/boot/dts/ingenic/Makefile                |  10 +
>  arch/mips/boot/dts/ingenic/ci20.dts                |  21 +
>  arch/mips/boot/dts/ingenic/jz4740.dtsi             |  68 ++
>  arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++
>  arch/mips/boot/dts/ingenic/qi_lb60.dts             |  15 +
>  arch/mips/configs/ci20_defconfig                   | 169 ++++
>  arch/mips/configs/qi_lb60_defconfig                |   3 +-
>  arch/mips/include/asm/cpu-type.h                   |   2 +-
>  arch/mips/include/asm/cpu.h                        |   6 +-
>  arch/mips/include/asm/mach-jz4740/clock.h          |   3 +
>  .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
>  arch/mips/include/asm/mach-jz4740/irq.h            |  14 +-
>  arch/mips/include/asm/mach-jz4740/platform.h       |   2 -
>  arch/mips/jz4740/Kconfig                           |  17 +-
>  arch/mips/jz4740/Makefile                          |   8 +-
>  arch/mips/jz4740/Platform                          |   8 +-
>  arch/mips/jz4740/board-qi_lb60.c                   |   7 -
>  arch/mips/jz4740/clock-debugfs.c                   | 108 ---
>  arch/mips/jz4740/clock.c                           | 924 ---------------------
>  arch/mips/jz4740/clock.h                           |  76 --
>  arch/mips/jz4740/gpio.c                            |   7 +-
>  arch/mips/jz4740/irq.c                             | 162 ----
>  arch/mips/jz4740/platform.c                        |  38 +-
>  arch/mips/jz4740/pm.c                              |   2 -
>  arch/mips/jz4740/prom.c                            |  13 -
>  arch/mips/jz4740/reset.c                           |  13 +-
>  arch/mips/jz4740/serial.c                          |  33 -
>  arch/mips/jz4740/serial.h                          |  23 -
>  arch/mips/jz4740/setup.c                           |  36 +-
>  arch/mips/jz4740/time.c                            |  19 +-
>  arch/mips/kernel/cpu-probe.c                       |   4 +-
>  arch/mips/kernel/irq_cpu.c                         |   3 +
>  drivers/clk/Makefile                               |   1 +
>  drivers/clk/ingenic/Makefile                       |   3 +
>  drivers/clk/ingenic/cgu.c                          | 711 ++++++++++++++++
>  drivers/clk/ingenic/cgu.h                          | 223 +++++
>  drivers/clk/ingenic/jz4740-cgu.c                   | 301 +++++++
>  drivers/clk/ingenic/jz4780-cgu.c                   | 732 ++++++++++++++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-ingenic.c                      | 171 ++++
>  drivers/tty/serial/8250/8250_ingenic.c             | 261 ++++++
>  drivers/tty/serial/8250/Kconfig                    |   9 +
>  drivers/tty/serial/8250/Makefile                   |   3 +
>  include/dt-bindings/clock/jz4740-cgu.h             |  37 +
>  include/dt-bindings/clock/jz4780-cgu.h             |  88 ++
>  .../irq.h => include/linux/irqchip/ingenic.h       |   8 +-
>  53 files changed, 3162 insertions(+), 1424 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
>  create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
>  create mode 100644 arch/mips/boot/dts/ingenic/Makefile
>  create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts
>  create mode 100644 arch/mips/configs/ci20_defconfig
>  delete mode 100644 arch/mips/jz4740/clock-debugfs.c
>  delete mode 100644 arch/mips/jz4740/clock.c
>  delete mode 100644 arch/mips/jz4740/clock.h
>  delete mode 100644 arch/mips/jz4740/irq.c
>  delete mode 100644 arch/mips/jz4740/serial.c
>  delete mode 100644 arch/mips/jz4740/serial.h
>  create mode 100644 drivers/clk/ingenic/Makefile
>  create mode 100644 drivers/clk/ingenic/cgu.c
>  create mode 100644 drivers/clk/ingenic/cgu.h
>  create mode 100644 drivers/clk/ingenic/jz4740-cgu.c
>  create mode 100644 drivers/clk/ingenic/jz4780-cgu.c
>  create mode 100644 drivers/irqchip/irq-ingenic.c
>  create mode 100644 drivers/tty/serial/8250/8250_ingenic.c
>  create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
>  create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
>  rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (74%)
>
> --
> 2.3.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v3 00/37] JZ4780 & CI20 support
@ 2015-04-22  4:06     ` Rob Herring
  0 siblings, 0 replies; 102+ messages in thread
From: Rob Herring @ 2015-04-22  4:06 UTC (permalink / raw)
  To: Paul Burton
  Cc: Linux-MIPS, Lars-Peter Clausen, Paul Cercueil, Thomas Gleixner,
	Jason Cooper, Mike Turquette, Greg Kroah-Hartman, devicetree,
	linux-serial

On Tue, Apr 21, 2015 at 9:46 AM, Paul Burton <paul.burton@imgtec.com> wrote:
> This series introduces initial support for the Ingenic JZ4780 SoC and
> the Imagination Technologies MIPS Creator CI20 board which is built
> around it. In the process the existing JZ4740 & qi_lb60 code gains
> initial support for using DeviceTree such that much of the existing
> platform code under arch/mips/jz4740 can be shared.
>
> The series has undergone quite a bit of restructure since v2. Each
> patch contains a changelog indicating its differences, but a rough
> overview for changes across the series would be:
>
>   - s/jz47xx/ingenic/ in various places, to reflect the fact that
>     Ingenic have changed the naming scheme for their newest SoCs
>     (now Mxxx).
>
>   - Restructure the Kconfig entries to provide a MACH_INGENIC
>     indicating and Ingenic SoC, and have boards select the
>     appropriate SoC symbol.
>
>   - Merge DT binding documentation where SoC bindings differ only
>     by compatible strings.
>
>   - Capitalise "JZ" in SoC names, where not identifiers in code,
>     to match the way Ingenic write them.
>
>   - Further clean up the Ingenic SoC interrupt controller driver
>     and move it under drivers/irqchip/.
>
> Review appreciated, and hopefully this can make it into v4.2.
>
> Thanks,
>     Paul
>
> Paul Burton (37):
>   devicetree/bindings: add Ingenic Semiconductor vendor prefix
>   devicetree/bindings: add Qi Hardware vendor prefix
>   MIPS: JZ4740: introduce CONFIG_MACH_INGENIC
>   MIPS: ingenic: add newer vendor IDs
>   MIPS: JZ4740: require & include DT
>   MIPS: irq_cpu: declare irqchip table entry
>   MIPS: JZ4740: probe CPU interrupt controller via DT
>   MIPS: JZ4740: use generic plat_irq_dispatch
>   MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c
>   devicetree: document Ingenic SoC interrupt controller binding

For patches 1, 2, and 10:

Acked-by: Rob Herring <robh@kernel.org>

>   MIPS: JZ4740: probe interrupt controller via DT
>   MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT
>   MIPS: JZ4740: register an irq_domain for the interrupt controller
>   MIPS: JZ4740: drop intc debugfs code
>   MIPS: JZ4740: remove jz_intc_base global
>   MIPS: JZ4740: support >32 interrupts
>   MIPS: JZ4740: define IRQ numbers based on number of intc IRQs
>   MIPS: JZ4740: read intc base address from DT
>   MIPS: JZ4740: avoid JZ4740-specific naming
>   MIPS: JZ4740: support newer SoC interrupt controllers
>   irqchip: move Ingenic SoC intc driver to drivers/irqchip
>   MIPS: JZ4740: call jz4740_clock_init earlier
>   MIPS: JZ4740: replace use of jz4740_clock_bdata
>   devicetree: add Ingenic CGU binding documentation
>   clk: ingenic: add driver for Ingenic SoC CGU clocks
>   MIPS,clk: migrate JZ4740 to common clock framework
>   MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu
>   MIPS,clk: move jz4740 UDC auto suspend functions to jz4740-cgu
>   MIPS,clk: move jz4740 clock suspend,resume functions to jz4740-cgu
>   clk: ingenic: add JZ4780 CGU support
>   MIPS: JZ4740: remove clock.h
>   MIPS: JZ4740: only detect RAM size if not specified in DT
>   devicetree: document Ingenic SoC UART binding
>   serial: 8250_ingenic: support for Ingenic SoC UARTs
>   MIPS: JZ4740: use Ingenic SoC UART driver
>   MIPS: ingenic: initial JZ4780 support
>   MIPS: ingenic: initial MIPS Creator CI20 support
>
>  .../devicetree/bindings/clock/ingenic,cgu.txt      |  53 ++
>  .../bindings/interrupt-controller/ingenic,intc.txt |  25 +
>  .../devicetree/bindings/serial/ingenic,uart.txt    |  22 +
>  .../devicetree/bindings/vendor-prefixes.txt        |   2 +
>  arch/mips/Kconfig                                  |  11 +-
>  arch/mips/boot/dts/Makefile                        |   1 +
>  arch/mips/boot/dts/ingenic/Makefile                |  10 +
>  arch/mips/boot/dts/ingenic/ci20.dts                |  21 +
>  arch/mips/boot/dts/ingenic/jz4740.dtsi             |  68 ++
>  arch/mips/boot/dts/ingenic/jz4780.dtsi             | 101 +++
>  arch/mips/boot/dts/ingenic/qi_lb60.dts             |  15 +
>  arch/mips/configs/ci20_defconfig                   | 169 ++++
>  arch/mips/configs/qi_lb60_defconfig                |   3 +-
>  arch/mips/include/asm/cpu-type.h                   |   2 +-
>  arch/mips/include/asm/cpu.h                        |   6 +-
>  arch/mips/include/asm/mach-jz4740/clock.h          |   3 +
>  .../asm/mach-jz4740/cpu-feature-overrides.h        |   3 -
>  arch/mips/include/asm/mach-jz4740/irq.h            |  14 +-
>  arch/mips/include/asm/mach-jz4740/platform.h       |   2 -
>  arch/mips/jz4740/Kconfig                           |  17 +-
>  arch/mips/jz4740/Makefile                          |   8 +-
>  arch/mips/jz4740/Platform                          |   8 +-
>  arch/mips/jz4740/board-qi_lb60.c                   |   7 -
>  arch/mips/jz4740/clock-debugfs.c                   | 108 ---
>  arch/mips/jz4740/clock.c                           | 924 ---------------------
>  arch/mips/jz4740/clock.h                           |  76 --
>  arch/mips/jz4740/gpio.c                            |   7 +-
>  arch/mips/jz4740/irq.c                             | 162 ----
>  arch/mips/jz4740/platform.c                        |  38 +-
>  arch/mips/jz4740/pm.c                              |   2 -
>  arch/mips/jz4740/prom.c                            |  13 -
>  arch/mips/jz4740/reset.c                           |  13 +-
>  arch/mips/jz4740/serial.c                          |  33 -
>  arch/mips/jz4740/serial.h                          |  23 -
>  arch/mips/jz4740/setup.c                           |  36 +-
>  arch/mips/jz4740/time.c                            |  19 +-
>  arch/mips/kernel/cpu-probe.c                       |   4 +-
>  arch/mips/kernel/irq_cpu.c                         |   3 +
>  drivers/clk/Makefile                               |   1 +
>  drivers/clk/ingenic/Makefile                       |   3 +
>  drivers/clk/ingenic/cgu.c                          | 711 ++++++++++++++++
>  drivers/clk/ingenic/cgu.h                          | 223 +++++
>  drivers/clk/ingenic/jz4740-cgu.c                   | 301 +++++++
>  drivers/clk/ingenic/jz4780-cgu.c                   | 732 ++++++++++++++++
>  drivers/irqchip/Kconfig                            |   5 +
>  drivers/irqchip/Makefile                           |   1 +
>  drivers/irqchip/irq-ingenic.c                      | 171 ++++
>  drivers/tty/serial/8250/8250_ingenic.c             | 261 ++++++
>  drivers/tty/serial/8250/Kconfig                    |   9 +
>  drivers/tty/serial/8250/Makefile                   |   3 +
>  include/dt-bindings/clock/jz4740-cgu.h             |  37 +
>  include/dt-bindings/clock/jz4780-cgu.h             |  88 ++
>  .../irq.h => include/linux/irqchip/ingenic.h       |   8 +-
>  53 files changed, 3162 insertions(+), 1424 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/ingenic,cgu.txt
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/ingenic,intc.txt
>  create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
>  create mode 100644 arch/mips/boot/dts/ingenic/Makefile
>  create mode 100644 arch/mips/boot/dts/ingenic/ci20.dts
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4740.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/jz4780.dtsi
>  create mode 100644 arch/mips/boot/dts/ingenic/qi_lb60.dts
>  create mode 100644 arch/mips/configs/ci20_defconfig
>  delete mode 100644 arch/mips/jz4740/clock-debugfs.c
>  delete mode 100644 arch/mips/jz4740/clock.c
>  delete mode 100644 arch/mips/jz4740/clock.h
>  delete mode 100644 arch/mips/jz4740/irq.c
>  delete mode 100644 arch/mips/jz4740/serial.c
>  delete mode 100644 arch/mips/jz4740/serial.h
>  create mode 100644 drivers/clk/ingenic/Makefile
>  create mode 100644 drivers/clk/ingenic/cgu.c
>  create mode 100644 drivers/clk/ingenic/cgu.h
>  create mode 100644 drivers/clk/ingenic/jz4740-cgu.c
>  create mode 100644 drivers/clk/ingenic/jz4780-cgu.c
>  create mode 100644 drivers/irqchip/irq-ingenic.c
>  create mode 100644 drivers/tty/serial/8250/8250_ingenic.c
>  create mode 100644 include/dt-bindings/clock/jz4740-cgu.h
>  create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
>  rename arch/mips/jz4740/irq.h => include/linux/irqchip/ingenic.h (74%)
>
> --
> 2.3.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v3 33/37] devicetree: document Ingenic SoC UART binding
  2015-04-21 14:47     ` Paul Burton
@ 2015-04-22  4:12         ` Rob Herring
  -1 siblings, 0 replies; 102+ messages in thread
From: Rob Herring @ 2015-04-22  4:12 UTC (permalink / raw)
  To: Paul Burton
  Cc: Linux-MIPS, Lars-Peter Clausen, devicetree-u79uwXL29TY76Z2rM5mHXA

On Tue, Apr 21, 2015 at 9:47 AM, Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org> wrote:
> Add binding documentation for the UARTs found in Ingenic SoCs.
>
> Signed-off-by: Paul Burton <paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
> Cc: Lars-Peter Clausen <lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org>
> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org

And for this one too:

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

> ---
> Changes in v3:
>   - Merge binding documentation for Ingenic SoCs whose bindings differ
>     only by their compatible strings.
>
> Changes in v2:
>   - None.
> ---
>  .../devicetree/bindings/serial/ingenic,uart.txt    | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
>
> diff --git a/Documentation/devicetree/bindings/serial/ingenic,uart.txt b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
> new file mode 100644
> index 0000000..c2d3b3a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
> @@ -0,0 +1,22 @@
> +* Ingenic SoC UART
> +
> +Required properties:
> +- compatible : "ingenic,jz4740-uart" or "ingenic,jz4780-uart"
> +- reg : offset and length of the register set for the device.
> +- interrupts : should contain uart interrupt.
> +- clocks : phandles to the module & baud clocks.
> +- clock-names: tuple listing input clock names.
> +       Required elements: "baud", "module"
> +
> +Example:
> +
> +uart0: serial@10030000 {
> +       compatible = "ingenic,jz4740-uart";
> +       reg = <0x10030000 0x100>;
> +
> +       interrupt-parent = <&intc>;
> +       interrupts = <9>;
> +
> +       clocks = <&ext>, <&cgu JZ4740_CLK_UART0>;
> +       clock-names = "baud", "module";
> +};
> --
> 2.3.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v3 33/37] devicetree: document Ingenic SoC UART binding
@ 2015-04-22  4:12         ` Rob Herring
  0 siblings, 0 replies; 102+ messages in thread
From: Rob Herring @ 2015-04-22  4:12 UTC (permalink / raw)
  To: Paul Burton; +Cc: Linux-MIPS, Lars-Peter Clausen, devicetree

On Tue, Apr 21, 2015 at 9:47 AM, Paul Burton <paul.burton@imgtec.com> wrote:
> Add binding documentation for the UARTs found in Ingenic SoCs.
>
> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> Cc: Lars-Peter Clausen <lars@metafoo.de>
> Cc: devicetree@vger.kernel.org

And for this one too:

Acked-by: Rob Herring <robh@kernel.org>

> ---
> Changes in v3:
>   - Merge binding documentation for Ingenic SoCs whose bindings differ
>     only by their compatible strings.
>
> Changes in v2:
>   - None.
> ---
>  .../devicetree/bindings/serial/ingenic,uart.txt    | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/serial/ingenic,uart.txt
>
> diff --git a/Documentation/devicetree/bindings/serial/ingenic,uart.txt b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
> new file mode 100644
> index 0000000..c2d3b3a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/serial/ingenic,uart.txt
> @@ -0,0 +1,22 @@
> +* Ingenic SoC UART
> +
> +Required properties:
> +- compatible : "ingenic,jz4740-uart" or "ingenic,jz4780-uart"
> +- reg : offset and length of the register set for the device.
> +- interrupts : should contain uart interrupt.
> +- clocks : phandles to the module & baud clocks.
> +- clock-names: tuple listing input clock names.
> +       Required elements: "baud", "module"
> +
> +Example:
> +
> +uart0: serial@10030000 {
> +       compatible = "ingenic,jz4740-uart";
> +       reg = <0x10030000 0x100>;
> +
> +       interrupt-parent = <&intc>;
> +       interrupts = <9>;
> +
> +       clocks = <&ext>, <&cgu JZ4740_CLK_UART0>;
> +       clock-names = "baud", "module";
> +};
> --
> 2.3.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v3 25/37] clk: ingenic: add driver for Ingenic SoC CGU clocks
@ 2015-04-22  8:52       ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-22  8:52 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Mike Turquette

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

On Wed, Apr 22, 2015 at 12:25:32AM +0100, James Hogan wrote:
> On Tue, Apr 21, 2015 at 03:46:52PM +0100, Paul Burton wrote:
> > +static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx)
> > +{
> > +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> > +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> > +	const struct ingenic_cgu_clk_info *clk_info;
> > +	unsigned long flags;
> > +	u8 curr_idx, hw_idx, num_poss;
> > +	u32 reg, mask;
> > +
> > +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> > +
> > +	if (clk_info->type & CGU_CLK_MUX) {
> > +		/*
> > +		 * Convert the parent index to the hardware index by adding
> > +		 * 1 for any -1 in the parents array preceding the given
> > +		 * index. That is, we want the index of idx'th entry in
> > +		 * clk_info->parents which does not equal -1.
> > +		 */
> > +		hw_idx = curr_idx = 0;
> > +		num_poss = 1 << clk_info->mux.bits;
> > +		for (; (hw_idx < num_poss) && (curr_idx != idx); hw_idx++) {
> 
> if idx==0, this'll never iterate since curr_idx starts at 0, even if the
> first parent is -1. It's basically an off-by-one error I think.
> 
> > +			if (clk_info->parents[hw_idx] == -1)
> > +				continue;
> > +			curr_idx++;
> 
> maybe move the curr_idx == idx check here.

Sorry. Before the curr_idx++ would of course be better.

> Its getting late. I'll continue looking at this patch some other time.

Here goes...

> > +
> > +static int ingenic_clk_enable(struct clk_hw *hw)
> > +{
> > +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> > +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> > +	const struct ingenic_cgu_clk_info *clk_info;
> > +	unsigned long flags;
> > +
> > +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> > +
> > +	if (clk_info->type & CGU_CLK_GATE) {
> > +		/* ungate the clock */
> > +		spin_lock_irqsave(&cgu->power_lock, flags);
> > +		ingenic_cgu_gate_set(cgu, &clk_info->gate, false);
> > +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void ingenic_clk_disable(struct clk_hw *hw)
> > +{
> > +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> > +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> > +	const struct ingenic_cgu_clk_info *clk_info;
> > +	unsigned long flags;
> > +
> > +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> > +
> > +	if (clk_info->type & CGU_CLK_GATE) {
> > +		/* gate the clock */
> > +		spin_lock_irqsave(&cgu->power_lock, flags);
> > +		ingenic_cgu_gate_set(cgu, &clk_info->gate, true);
> > +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> > +	}
> > +}
> > +
> > +static int ingenic_clk_is_enabled(struct clk_hw *hw)
> > +{
> > +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> > +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> > +	const struct ingenic_cgu_clk_info *clk_info;
> > +	unsigned long flags;
> > +	int enabled = 1;
> > +
> > +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> > +
> > +	if (clk_info->type & CGU_CLK_GATE) {
> > +		spin_lock_irqsave(&cgu->power_lock, flags);
> > +		enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
> > +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> > +	}
> > +
> > +	return enabled;
> > +}
> > +
> > +static const struct clk_ops ingenic_clk_ops = {
> > +	.get_parent = ingenic_clk_get_parent,
> > +	.set_parent = ingenic_clk_set_parent,
> > +
> > +	.recalc_rate = ingenic_clk_recalc_rate,
> > +	.round_rate = ingenic_clk_round_rate,
> > +	.set_rate = ingenic_clk_set_rate,
> > +
> > +	.enable = ingenic_clk_enable,
> > +	.disable = ingenic_clk_disable,
> > +	.is_enabled = ingenic_clk_is_enabled,
> > +};
> > +
> > +/*
> > + * Setup functions.
> > + */
> > +
> > +static int register_clock(struct ingenic_cgu *cgu, unsigned idx)
> > +{
> > +	const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx];
> > +	struct clk_init_data clk_init;
> > +	struct ingenic_clk *ingenic_clk = NULL;
> > +	struct clk *clk, *parent;
> > +	const char *parent_names[4];
> > +	unsigned caps, i, num_possible;
> > +	int err = -EINVAL;
> > +
> > +	BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names));
> > +
> > +	if (clk_info->type == CGU_CLK_EXT) {
> > +		clk = of_clk_get_by_name(cgu->np, clk_info->name);
> > +		if (IS_ERR(clk)) {
> > +			pr_err("%s: no external clock '%s' provided\n",
> > +			       __func__, clk_info->name);
> > +			err = -ENODEV;
> > +			goto out;
> > +		}
> > +		err = clk_register_clkdev(clk, clk_info->name, NULL);
> > +		if (err) {
> > +			clk_put(clk);
> > +			goto out;
> > +		}
> > +		cgu->clocks.clks[idx] = clk;
> > +		return 0;
> > +	}
> > +
> > +	if (!clk_info->type) {
> > +		pr_err("%s: no clock type specified for '%s'\n", __func__,
> > +		       clk_info->name);
> > +		goto out;
> > +	}
> > +
> > +	ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL);
> > +	if (!ingenic_clk) {
> > +		err = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	ingenic_clk->hw.init = &clk_init;
> > +	ingenic_clk->cgu = cgu;
> > +	ingenic_clk->idx = idx;
> > +
> > +	clk_init.name = clk_info->name;
> > +	clk_init.flags = 0;
> > +	clk_init.parent_names = parent_names;
> > +
> > +	caps = clk_info->type;
> > +
> > +	if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
> > +		clk_init.num_parents = 0;
> > +
> > +		if (caps & CGU_CLK_MUX)
> > +			num_possible = 1 << clk_info->mux.bits;
> > +		else
> > +			num_possible = ARRAY_SIZE(clk_info->parents);
> > +
> > +		for (i = 0; i < num_possible; i++) {
> > +			if (clk_info->parents[i] == -1)
> > +				continue;
> > +
> > +			parent = cgu->clocks.clks[clk_info->parents[i]];
> > +			parent_names[clk_init.num_parents] =
> > +				__clk_get_name(parent);
> > +			clk_init.num_parents++;
> > +		}
> > +
> > +		BUG_ON(!clk_init.num_parents);
> > +		BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names));
> > +	} else {
> > +		BUG_ON(clk_info->parents[0] == -1);
> > +		clk_init.num_parents = 1;
> > +		parent = cgu->clocks.clks[clk_info->parents[0]];
> > +		parent_names[0] = __clk_get_name(parent);
> > +	}
> > +
> > +	if (caps & CGU_CLK_CUSTOM) {
> > +		clk_init.ops = clk_info->custom.clk_ops;
> > +
> > +		caps &= ~CGU_CLK_CUSTOM;
> > +
> > +		if (caps) {
> > +			pr_err("%s: custom clock may not be combined with type 0x%x\n",
> > +			       __func__, caps);
> > +			goto out;
> > +		}
> > +	} else if (caps & CGU_CLK_PLL) {
> > +		clk_init.ops = &ingenic_pll_ops;
> > +
> > +		caps &= ~CGU_CLK_PLL;
> > +
> > +		if (caps) {
> > +			pr_err("%s: PLL may not be combined with type 0x%x\n",
> > +			       __func__, caps);
> > +			goto out;
> > +		}
> > +	} else {
> > +		clk_init.ops = &ingenic_clk_ops;
> > +	}
> > +
> > +	/* nothing to do for gates or fixed dividers */
> > +	caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV);
> > +
> > +	if (caps & CGU_CLK_MUX) {
> > +		if (!(caps & CGU_CLK_MUX_GLITCHFREE))
> > +			clk_init.flags |= CLK_SET_PARENT_GATE;
> > +
> > +		caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE);
> > +	}
> > +
> > +	if (caps & CGU_CLK_DIV) {
> > +		caps &= ~CGU_CLK_DIV;
> > +	} else {
> > +		/* pass rate changes to the parent clock */
> > +		clk_init.flags |= CLK_SET_RATE_PARENT;
> > +	}
> > +
> > +	if (caps) {
> > +		pr_err("%s: unknown clock type 0x%x\n", __func__, caps);
> > +		goto out;
> > +	}
> > +
> > +	clk = clk_register(NULL, &ingenic_clk->hw);
> > +	if (IS_ERR(clk)) {
> > +		pr_err("%s: failed to register clock '%s'\n", __func__,
> > +		       clk_info->name);
> > +		err = PTR_ERR(clk);
> > +		goto out;
> > +	}
> > +
> > +	err = clk_register_clkdev(clk, clk_info->name, NULL);
> > +	if (err)
> > +		goto out;

Should this unregister the clock in case of failure?

> > +
> > +	cgu->clocks.clks[idx] = clk;
> > +out:
> > +	if (err)
> > +		kfree(ingenic_clk);
> > +	return err;
> > +}
> > +
> > +struct ingenic_cgu *
> > +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
> > +		unsigned num_clocks, struct device_node *np)
> > +{
> > +	struct ingenic_cgu *cgu;
> > +
> > +	cgu = kzalloc(sizeof(*cgu), GFP_KERNEL);
> > +	if (!cgu)
> > +		goto err_out;
> > +
> > +	cgu->base = of_iomap(np, 0);
> > +	if (!cgu->base) {
> > +		pr_err("%s: failed to map CGU registers\n", __func__);
> > +		goto err_out_free;
> > +	}
> > +
> > +	cgu->np = np;
> > +	cgu->clock_info = clock_info;
> > +	cgu->clocks.clk_num = num_clocks;
> > +
> > +	spin_lock_init(&cgu->divmux_lock);
> > +	spin_lock_init(&cgu->power_lock);
> > +	spin_lock_init(&cgu->pll_lock);
> > +
> > +	return cgu;
> > +
> > +err_out_free:
> > +	kfree(cgu);
> > +err_out:
> > +	return NULL;
> > +}
> > +
> > +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu)
> > +{
> > +	unsigned i;
> > +	int err;
> > +
> > +	cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *),
> > +				   GFP_KERNEL);
> > +	if (!cgu->clocks.clks) {
> > +		err = -ENOMEM;
> > +		goto err_out;
> > +	}
> > +
> > +	for (i = 0; i < cgu->clocks.clk_num; i++) {
> > +		err = register_clock(cgu, i);
> > +		if (err)
> > +			goto err_out_unregister;
> > +	}
> > +
> > +	err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get,
> > +				  &cgu->clocks);
> > +	if (err)
> > +		goto err_out_unregister;
> > +
> > +	return 0;
> > +
> > +err_out_unregister:
> > +	if (cgu) {

This check looks redundant, since the rest of the function already assumes
non-NULL.

> > +		for (i = 0; i < cgu->clocks.clk_num; i++) {
> > +			if (!cgu->clocks.clks[i])
> > +				continue;
> > +			if (cgu->clock_info[i].type & CGU_CLK_EXT)
> > +				clk_put(cgu->clocks.clks[i]);
> > +			else
> > +				clk_unregister(cgu->clocks.clks[i]);
> > +		}
> > +		kfree(cgu->clocks.clks);
> > +	}
> > +err_out:
> > +	return err;
> > +}
> > diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
> > new file mode 100644
> > index 0000000..47e0552
> > --- /dev/null
> > +++ b/drivers/clk/ingenic/cgu.h
> > @@ -0,0 +1,223 @@
> > +/*
> > + * Ingenic SoC CGU driver
> > + *
> > + * Copyright (c) 2013-2015 Imagination Technologies
> > + * Author: Paul Burton <paul.burton@imgtec.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef __DRIVERS_CLK_INGENIC_CGU_H__
> > +#define __DRIVERS_CLK_INGENIC_CGU_H__
> > +
> > +#include <linux/of.h>
> > +#include <linux/spinlock.h>
> > +
> > +/**
> > + * struct ingenic_cgu_pll_info - information about a PLL
> > + * @reg: the offset of the PLL's control register within the CGU
> > + * @m_shift: the number of bits to shift the multiplier value by (ie. the
> > + *           index of the lowest bit of the multiplier value in the PLL's
> > + *           control register)
> > + * @m_bits: the size of the multiplier field in bits
> > + * @m_offset: the multiplier value which encodes to 0 in the PLL's control
> > + *            register
> > + * @n_shift: the number of bits to shift the divider value by (ie. the
> > + *           index of the lowest bit of the divider value in the PLL's
> > + *           control register)
> > + * @n_bits: the size of the divider field in bits
> > + * @n_offset: the divider value which encodes to 0 in the PLL's control
> > + *            register
> > + * @od_shift: the number of bits to shift the post-VCO divider value by (ie.
> > + *            the index of the lowest bit of the post-VCO divider value in
> > + *            the PLL's control register)
> > + * @od_bits: the size of the post-VCO divider field in bits
> > + * @od_max: the maximum post-VCO divider value
> > + * @od_encoding: a pointer to an array mapping post-VCO divider values to
> > + *               their encoded values in the PLL control register, or -1 for
> > + *               unsupported values
> > + * @bypass_bit: the index of the bypass bit in the PLL control register
> > + * @enable_bit: the index of the enable bit in the PLL control register
> > + * @stable_bit: the index of the stable bit in the PLL control register
> > + */
> > +struct ingenic_cgu_pll_info {
> > +	unsigned reg;
> > +	unsigned m_shift, m_bits, m_offset;
> > +	unsigned n_shift, n_bits, n_offset;
> > +	unsigned od_shift, od_bits, od_max;
> > +	const s8 *od_encoding;
> > +	unsigned bypass_bit;
> > +	unsigned enable_bit;
> > +	unsigned stable_bit;

I suppose a bunch of these could be reduced to u8's, but no big deal...

> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_mux_info - information about a clock mux
> > + * @reg: offset of the mux control register within the CGU
> > + * @shift: number of bits to shift the mux value by (ie. the index of
> > + *         the lowest bit of the mux value within its control register)
> > + * @bits: the size of the mux value in bits
> > + */
> > +struct ingenic_cgu_mux_info {
> > +	unsigned reg;
> > +	unsigned shift:5;
> > +	unsigned bits:5;

... especially as this seems to go to the other extreme

> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_div_info - information about a divider
> > + * @reg: offset of the divider control register within the CGU
> > + * @shift: number of bits to shift the divide value by (ie. the index of
> > + *         the lowest bit of the divide value within its control register)
> > + * @bits: the size of the divide value in bits
> > + * @ce_bit: the index of the change enable bit within reg, or -1 is there
> > + *          isn't one
> > + * @busy_bit: the index of the busy bit within reg, or -1 is there isn't one
> > + * @stop_bit: the index of the stop bit within reg, or -1 is there isn't one

s/is/if/ for all 3 *_bit fields?

> > + */
> > +struct ingenic_cgu_div_info {
> > +	unsigned reg;
> > +	unsigned shift:5;
> > +	unsigned bits:5;
> > +	int ce_bit:6;
> > +	int busy_bit:6;
> > +	int stop_bit:6;
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_fixdiv_info - information about a fixed divider
> > + * @div: the divider applied to the parent clock
> > + */
> > +struct ingenic_cgu_fixdiv_info {
> > +	unsigned div;
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_gate_info - information about a clock gate
> > + * @reg: offset of the gate control register within the CGU
> > + * @bit: offset of the bit in the register that controls the gate
> > + */
> > +struct ingenic_cgu_gate_info {
> > +	unsigned reg;
> > +	unsigned bit:5;
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_custom_info - information about a custom (SoC) clock

no description of clk_ops.

> > + */
> > +struct ingenic_cgu_custom_info {
> > +	struct clk_ops *clk_ops;
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_clk_info - information about a clock
> > + * @name: name of the clock
> > + * @type: a bitmask formed from CGU_CLK_* values
> > + * @parents: an array of the indices of potential parents of this clock
> > + *           within the clock_info array of the CGU, or -1 in entries
> > + *           which correspond to no valid parent
> > + * @pll: information valid if type includes CGU_CLK_PLL
> > + * @gate: information valid if type includes CGU_CLK_GATE
> > + * @mux: information valid if type includes CGU_CLK_MUX
> > + * @div: information valid if type includes CGU_CLK_DIV

fixdiv and custom are undescribed.

> > + */
> > +struct ingenic_cgu_clk_info {
> > +	const char *name;
> > +
> > +	enum {
> > +		CGU_CLK_NONE		= 0,
> > +		CGU_CLK_EXT		= (1 << 0),
> > +		CGU_CLK_PLL		= (1 << 1),
> > +		CGU_CLK_GATE		= (1 << 2),
> > +		CGU_CLK_MUX		= (1 << 3),
> > +		CGU_CLK_MUX_GLITCHFREE	= (1 << 4),
> > +		CGU_CLK_DIV		= (1 << 5),
> > +		CGU_CLK_FIXDIV		= (1 << 6),
> > +		CGU_CLK_CUSTOM		= (1 << 7),

Appropriate to use BIT() from <linux/bitops.h> here?

> > +	} type;
> > +
> > +	int parents[4];
> > +
> > +	union {
> > +		struct ingenic_cgu_pll_info pll;
> > +
> > +		struct {
> > +			struct ingenic_cgu_gate_info gate;
> > +			struct ingenic_cgu_mux_info mux;
> > +			struct ingenic_cgu_div_info div;
> > +			struct ingenic_cgu_fixdiv_info fixdiv;
> > +		};
> > +
> > +		struct ingenic_cgu_custom_info custom;
> > +	};
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu - data about the CGU
> > + * @np: the device tree node that caused the CGU to be probed
> > + * @base: the ioremap'ed base address of the CGU registers
> > + * @clock_info: an array containing information about implemented clocks
> > + * @clocks: used to provide clocks to DT, allows lookup of struct clk*
> > + * @gate_lock: lock to be held whilst (un)gating a clock

stale

> > + * @divmux_lock: lock to be held whilst re-muxing of rate-changing a clock

power_lock and pll_lock undescribed

> > + */
> > +struct ingenic_cgu {
> > +	struct device_node *np;
> > +	void __iomem *base;
> > +
> > +	const struct ingenic_cgu_clk_info *clock_info;
> > +	struct clk_onecell_data clocks;
> > +
> > +	spinlock_t divmux_lock;		/* must be held when changing a divide
> > +					   or re-muxing a clock */
> > +	spinlock_t power_lock;		/* must be held when changing a power
> > +					   manager register */
> > +	spinlock_t pll_lock;		/* must be held when changing a PLL
> > +					   control register */

those comments should go in the kernel doc description.

(Although see my previous email about locking in common clock framework).

> > +};
> > +
> > +/**
> > + * struct ingenic_clk - private data for a clock
> > + * @hw: see Documentation/clk.txt
> > + * @cgu: a pointer to the CGU data
> > + * @idx: the index of this clock in cgu->clock_info
> > + */
> > +struct ingenic_clk {
> > +	struct clk_hw hw;
> > +	struct ingenic_cgu *cgu;
> > +	unsigned idx;
> > +};
> > +
> > +#define to_ingenic_clk(_hw) container_of(_hw, struct ingenic_clk, hw)
> > +
> > +/**
> > + * ingenic_cgu_new - create a new CGU instance

function, so needs ()

> > + * @clock_info: an array of clock information structures describing the clocks
> > + *              which are implemented by the CGU
> > + * @num_clocks: the number of entries in clock_info
> > + * @np: the device tree node which causes this CGU to be probed
> > + *
> > + * Returns an opaque pointer to the CGU instance if initialisation & clock
> > + * registration is successful, otherwise NULL.

As above, do this sort of thing:
 * Return:	an opaque pointer to the CGU instance if initialisation & clock
 *		registration is successful, otherwise NULL.

> > + */
> > +struct ingenic_cgu *
> > +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
> > +		unsigned num_clocks, struct device_node *np);
> > +
> > +/**
> > + * ingenic_cgu_register_clocks - Registers the clocks
> > + * @cgu: pointer to cgu data
> > + *
> > + * Returns 1 on success and -EINVAL if unsuccesful.

same

> > + */
> > +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu);
> > +
> > +#endif /* __DRIVERS_CLK_INGENIC_CGU_H__ */

Nice work guys!

Cheers
James

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

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

* Re: [PATCH v3 25/37] clk: ingenic: add driver for Ingenic SoC CGU clocks
@ 2015-04-22  8:52       ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-22  8:52 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Mike Turquette

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

On Wed, Apr 22, 2015 at 12:25:32AM +0100, James Hogan wrote:
> On Tue, Apr 21, 2015 at 03:46:52PM +0100, Paul Burton wrote:
> > +static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx)
> > +{
> > +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> > +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> > +	const struct ingenic_cgu_clk_info *clk_info;
> > +	unsigned long flags;
> > +	u8 curr_idx, hw_idx, num_poss;
> > +	u32 reg, mask;
> > +
> > +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> > +
> > +	if (clk_info->type & CGU_CLK_MUX) {
> > +		/*
> > +		 * Convert the parent index to the hardware index by adding
> > +		 * 1 for any -1 in the parents array preceding the given
> > +		 * index. That is, we want the index of idx'th entry in
> > +		 * clk_info->parents which does not equal -1.
> > +		 */
> > +		hw_idx = curr_idx = 0;
> > +		num_poss = 1 << clk_info->mux.bits;
> > +		for (; (hw_idx < num_poss) && (curr_idx != idx); hw_idx++) {
> 
> if idx==0, this'll never iterate since curr_idx starts at 0, even if the
> first parent is -1. It's basically an off-by-one error I think.
> 
> > +			if (clk_info->parents[hw_idx] == -1)
> > +				continue;
> > +			curr_idx++;
> 
> maybe move the curr_idx == idx check here.

Sorry. Before the curr_idx++ would of course be better.

> Its getting late. I'll continue looking at this patch some other time.

Here goes...

> > +
> > +static int ingenic_clk_enable(struct clk_hw *hw)
> > +{
> > +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> > +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> > +	const struct ingenic_cgu_clk_info *clk_info;
> > +	unsigned long flags;
> > +
> > +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> > +
> > +	if (clk_info->type & CGU_CLK_GATE) {
> > +		/* ungate the clock */
> > +		spin_lock_irqsave(&cgu->power_lock, flags);
> > +		ingenic_cgu_gate_set(cgu, &clk_info->gate, false);
> > +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static void ingenic_clk_disable(struct clk_hw *hw)
> > +{
> > +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> > +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> > +	const struct ingenic_cgu_clk_info *clk_info;
> > +	unsigned long flags;
> > +
> > +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> > +
> > +	if (clk_info->type & CGU_CLK_GATE) {
> > +		/* gate the clock */
> > +		spin_lock_irqsave(&cgu->power_lock, flags);
> > +		ingenic_cgu_gate_set(cgu, &clk_info->gate, true);
> > +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> > +	}
> > +}
> > +
> > +static int ingenic_clk_is_enabled(struct clk_hw *hw)
> > +{
> > +	struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
> > +	struct ingenic_cgu *cgu = ingenic_clk->cgu;
> > +	const struct ingenic_cgu_clk_info *clk_info;
> > +	unsigned long flags;
> > +	int enabled = 1;
> > +
> > +	clk_info = &cgu->clock_info[ingenic_clk->idx];
> > +
> > +	if (clk_info->type & CGU_CLK_GATE) {
> > +		spin_lock_irqsave(&cgu->power_lock, flags);
> > +		enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
> > +		spin_unlock_irqrestore(&cgu->power_lock, flags);
> > +	}
> > +
> > +	return enabled;
> > +}
> > +
> > +static const struct clk_ops ingenic_clk_ops = {
> > +	.get_parent = ingenic_clk_get_parent,
> > +	.set_parent = ingenic_clk_set_parent,
> > +
> > +	.recalc_rate = ingenic_clk_recalc_rate,
> > +	.round_rate = ingenic_clk_round_rate,
> > +	.set_rate = ingenic_clk_set_rate,
> > +
> > +	.enable = ingenic_clk_enable,
> > +	.disable = ingenic_clk_disable,
> > +	.is_enabled = ingenic_clk_is_enabled,
> > +};
> > +
> > +/*
> > + * Setup functions.
> > + */
> > +
> > +static int register_clock(struct ingenic_cgu *cgu, unsigned idx)
> > +{
> > +	const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx];
> > +	struct clk_init_data clk_init;
> > +	struct ingenic_clk *ingenic_clk = NULL;
> > +	struct clk *clk, *parent;
> > +	const char *parent_names[4];
> > +	unsigned caps, i, num_possible;
> > +	int err = -EINVAL;
> > +
> > +	BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names));
> > +
> > +	if (clk_info->type == CGU_CLK_EXT) {
> > +		clk = of_clk_get_by_name(cgu->np, clk_info->name);
> > +		if (IS_ERR(clk)) {
> > +			pr_err("%s: no external clock '%s' provided\n",
> > +			       __func__, clk_info->name);
> > +			err = -ENODEV;
> > +			goto out;
> > +		}
> > +		err = clk_register_clkdev(clk, clk_info->name, NULL);
> > +		if (err) {
> > +			clk_put(clk);
> > +			goto out;
> > +		}
> > +		cgu->clocks.clks[idx] = clk;
> > +		return 0;
> > +	}
> > +
> > +	if (!clk_info->type) {
> > +		pr_err("%s: no clock type specified for '%s'\n", __func__,
> > +		       clk_info->name);
> > +		goto out;
> > +	}
> > +
> > +	ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL);
> > +	if (!ingenic_clk) {
> > +		err = -ENOMEM;
> > +		goto out;
> > +	}
> > +
> > +	ingenic_clk->hw.init = &clk_init;
> > +	ingenic_clk->cgu = cgu;
> > +	ingenic_clk->idx = idx;
> > +
> > +	clk_init.name = clk_info->name;
> > +	clk_init.flags = 0;
> > +	clk_init.parent_names = parent_names;
> > +
> > +	caps = clk_info->type;
> > +
> > +	if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
> > +		clk_init.num_parents = 0;
> > +
> > +		if (caps & CGU_CLK_MUX)
> > +			num_possible = 1 << clk_info->mux.bits;
> > +		else
> > +			num_possible = ARRAY_SIZE(clk_info->parents);
> > +
> > +		for (i = 0; i < num_possible; i++) {
> > +			if (clk_info->parents[i] == -1)
> > +				continue;
> > +
> > +			parent = cgu->clocks.clks[clk_info->parents[i]];
> > +			parent_names[clk_init.num_parents] =
> > +				__clk_get_name(parent);
> > +			clk_init.num_parents++;
> > +		}
> > +
> > +		BUG_ON(!clk_init.num_parents);
> > +		BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names));
> > +	} else {
> > +		BUG_ON(clk_info->parents[0] == -1);
> > +		clk_init.num_parents = 1;
> > +		parent = cgu->clocks.clks[clk_info->parents[0]];
> > +		parent_names[0] = __clk_get_name(parent);
> > +	}
> > +
> > +	if (caps & CGU_CLK_CUSTOM) {
> > +		clk_init.ops = clk_info->custom.clk_ops;
> > +
> > +		caps &= ~CGU_CLK_CUSTOM;
> > +
> > +		if (caps) {
> > +			pr_err("%s: custom clock may not be combined with type 0x%x\n",
> > +			       __func__, caps);
> > +			goto out;
> > +		}
> > +	} else if (caps & CGU_CLK_PLL) {
> > +		clk_init.ops = &ingenic_pll_ops;
> > +
> > +		caps &= ~CGU_CLK_PLL;
> > +
> > +		if (caps) {
> > +			pr_err("%s: PLL may not be combined with type 0x%x\n",
> > +			       __func__, caps);
> > +			goto out;
> > +		}
> > +	} else {
> > +		clk_init.ops = &ingenic_clk_ops;
> > +	}
> > +
> > +	/* nothing to do for gates or fixed dividers */
> > +	caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV);
> > +
> > +	if (caps & CGU_CLK_MUX) {
> > +		if (!(caps & CGU_CLK_MUX_GLITCHFREE))
> > +			clk_init.flags |= CLK_SET_PARENT_GATE;
> > +
> > +		caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE);
> > +	}
> > +
> > +	if (caps & CGU_CLK_DIV) {
> > +		caps &= ~CGU_CLK_DIV;
> > +	} else {
> > +		/* pass rate changes to the parent clock */
> > +		clk_init.flags |= CLK_SET_RATE_PARENT;
> > +	}
> > +
> > +	if (caps) {
> > +		pr_err("%s: unknown clock type 0x%x\n", __func__, caps);
> > +		goto out;
> > +	}
> > +
> > +	clk = clk_register(NULL, &ingenic_clk->hw);
> > +	if (IS_ERR(clk)) {
> > +		pr_err("%s: failed to register clock '%s'\n", __func__,
> > +		       clk_info->name);
> > +		err = PTR_ERR(clk);
> > +		goto out;
> > +	}
> > +
> > +	err = clk_register_clkdev(clk, clk_info->name, NULL);
> > +	if (err)
> > +		goto out;

Should this unregister the clock in case of failure?

> > +
> > +	cgu->clocks.clks[idx] = clk;
> > +out:
> > +	if (err)
> > +		kfree(ingenic_clk);
> > +	return err;
> > +}
> > +
> > +struct ingenic_cgu *
> > +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
> > +		unsigned num_clocks, struct device_node *np)
> > +{
> > +	struct ingenic_cgu *cgu;
> > +
> > +	cgu = kzalloc(sizeof(*cgu), GFP_KERNEL);
> > +	if (!cgu)
> > +		goto err_out;
> > +
> > +	cgu->base = of_iomap(np, 0);
> > +	if (!cgu->base) {
> > +		pr_err("%s: failed to map CGU registers\n", __func__);
> > +		goto err_out_free;
> > +	}
> > +
> > +	cgu->np = np;
> > +	cgu->clock_info = clock_info;
> > +	cgu->clocks.clk_num = num_clocks;
> > +
> > +	spin_lock_init(&cgu->divmux_lock);
> > +	spin_lock_init(&cgu->power_lock);
> > +	spin_lock_init(&cgu->pll_lock);
> > +
> > +	return cgu;
> > +
> > +err_out_free:
> > +	kfree(cgu);
> > +err_out:
> > +	return NULL;
> > +}
> > +
> > +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu)
> > +{
> > +	unsigned i;
> > +	int err;
> > +
> > +	cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *),
> > +				   GFP_KERNEL);
> > +	if (!cgu->clocks.clks) {
> > +		err = -ENOMEM;
> > +		goto err_out;
> > +	}
> > +
> > +	for (i = 0; i < cgu->clocks.clk_num; i++) {
> > +		err = register_clock(cgu, i);
> > +		if (err)
> > +			goto err_out_unregister;
> > +	}
> > +
> > +	err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get,
> > +				  &cgu->clocks);
> > +	if (err)
> > +		goto err_out_unregister;
> > +
> > +	return 0;
> > +
> > +err_out_unregister:
> > +	if (cgu) {

This check looks redundant, since the rest of the function already assumes
non-NULL.

> > +		for (i = 0; i < cgu->clocks.clk_num; i++) {
> > +			if (!cgu->clocks.clks[i])
> > +				continue;
> > +			if (cgu->clock_info[i].type & CGU_CLK_EXT)
> > +				clk_put(cgu->clocks.clks[i]);
> > +			else
> > +				clk_unregister(cgu->clocks.clks[i]);
> > +		}
> > +		kfree(cgu->clocks.clks);
> > +	}
> > +err_out:
> > +	return err;
> > +}
> > diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
> > new file mode 100644
> > index 0000000..47e0552
> > --- /dev/null
> > +++ b/drivers/clk/ingenic/cgu.h
> > @@ -0,0 +1,223 @@
> > +/*
> > + * Ingenic SoC CGU driver
> > + *
> > + * Copyright (c) 2013-2015 Imagination Technologies
> > + * Author: Paul Burton <paul.burton@imgtec.com>
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#ifndef __DRIVERS_CLK_INGENIC_CGU_H__
> > +#define __DRIVERS_CLK_INGENIC_CGU_H__
> > +
> > +#include <linux/of.h>
> > +#include <linux/spinlock.h>
> > +
> > +/**
> > + * struct ingenic_cgu_pll_info - information about a PLL
> > + * @reg: the offset of the PLL's control register within the CGU
> > + * @m_shift: the number of bits to shift the multiplier value by (ie. the
> > + *           index of the lowest bit of the multiplier value in the PLL's
> > + *           control register)
> > + * @m_bits: the size of the multiplier field in bits
> > + * @m_offset: the multiplier value which encodes to 0 in the PLL's control
> > + *            register
> > + * @n_shift: the number of bits to shift the divider value by (ie. the
> > + *           index of the lowest bit of the divider value in the PLL's
> > + *           control register)
> > + * @n_bits: the size of the divider field in bits
> > + * @n_offset: the divider value which encodes to 0 in the PLL's control
> > + *            register
> > + * @od_shift: the number of bits to shift the post-VCO divider value by (ie.
> > + *            the index of the lowest bit of the post-VCO divider value in
> > + *            the PLL's control register)
> > + * @od_bits: the size of the post-VCO divider field in bits
> > + * @od_max: the maximum post-VCO divider value
> > + * @od_encoding: a pointer to an array mapping post-VCO divider values to
> > + *               their encoded values in the PLL control register, or -1 for
> > + *               unsupported values
> > + * @bypass_bit: the index of the bypass bit in the PLL control register
> > + * @enable_bit: the index of the enable bit in the PLL control register
> > + * @stable_bit: the index of the stable bit in the PLL control register
> > + */
> > +struct ingenic_cgu_pll_info {
> > +	unsigned reg;
> > +	unsigned m_shift, m_bits, m_offset;
> > +	unsigned n_shift, n_bits, n_offset;
> > +	unsigned od_shift, od_bits, od_max;
> > +	const s8 *od_encoding;
> > +	unsigned bypass_bit;
> > +	unsigned enable_bit;
> > +	unsigned stable_bit;

I suppose a bunch of these could be reduced to u8's, but no big deal...

> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_mux_info - information about a clock mux
> > + * @reg: offset of the mux control register within the CGU
> > + * @shift: number of bits to shift the mux value by (ie. the index of
> > + *         the lowest bit of the mux value within its control register)
> > + * @bits: the size of the mux value in bits
> > + */
> > +struct ingenic_cgu_mux_info {
> > +	unsigned reg;
> > +	unsigned shift:5;
> > +	unsigned bits:5;

... especially as this seems to go to the other extreme

> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_div_info - information about a divider
> > + * @reg: offset of the divider control register within the CGU
> > + * @shift: number of bits to shift the divide value by (ie. the index of
> > + *         the lowest bit of the divide value within its control register)
> > + * @bits: the size of the divide value in bits
> > + * @ce_bit: the index of the change enable bit within reg, or -1 is there
> > + *          isn't one
> > + * @busy_bit: the index of the busy bit within reg, or -1 is there isn't one
> > + * @stop_bit: the index of the stop bit within reg, or -1 is there isn't one

s/is/if/ for all 3 *_bit fields?

> > + */
> > +struct ingenic_cgu_div_info {
> > +	unsigned reg;
> > +	unsigned shift:5;
> > +	unsigned bits:5;
> > +	int ce_bit:6;
> > +	int busy_bit:6;
> > +	int stop_bit:6;
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_fixdiv_info - information about a fixed divider
> > + * @div: the divider applied to the parent clock
> > + */
> > +struct ingenic_cgu_fixdiv_info {
> > +	unsigned div;
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_gate_info - information about a clock gate
> > + * @reg: offset of the gate control register within the CGU
> > + * @bit: offset of the bit in the register that controls the gate
> > + */
> > +struct ingenic_cgu_gate_info {
> > +	unsigned reg;
> > +	unsigned bit:5;
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_custom_info - information about a custom (SoC) clock

no description of clk_ops.

> > + */
> > +struct ingenic_cgu_custom_info {
> > +	struct clk_ops *clk_ops;
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu_clk_info - information about a clock
> > + * @name: name of the clock
> > + * @type: a bitmask formed from CGU_CLK_* values
> > + * @parents: an array of the indices of potential parents of this clock
> > + *           within the clock_info array of the CGU, or -1 in entries
> > + *           which correspond to no valid parent
> > + * @pll: information valid if type includes CGU_CLK_PLL
> > + * @gate: information valid if type includes CGU_CLK_GATE
> > + * @mux: information valid if type includes CGU_CLK_MUX
> > + * @div: information valid if type includes CGU_CLK_DIV

fixdiv and custom are undescribed.

> > + */
> > +struct ingenic_cgu_clk_info {
> > +	const char *name;
> > +
> > +	enum {
> > +		CGU_CLK_NONE		= 0,
> > +		CGU_CLK_EXT		= (1 << 0),
> > +		CGU_CLK_PLL		= (1 << 1),
> > +		CGU_CLK_GATE		= (1 << 2),
> > +		CGU_CLK_MUX		= (1 << 3),
> > +		CGU_CLK_MUX_GLITCHFREE	= (1 << 4),
> > +		CGU_CLK_DIV		= (1 << 5),
> > +		CGU_CLK_FIXDIV		= (1 << 6),
> > +		CGU_CLK_CUSTOM		= (1 << 7),

Appropriate to use BIT() from <linux/bitops.h> here?

> > +	} type;
> > +
> > +	int parents[4];
> > +
> > +	union {
> > +		struct ingenic_cgu_pll_info pll;
> > +
> > +		struct {
> > +			struct ingenic_cgu_gate_info gate;
> > +			struct ingenic_cgu_mux_info mux;
> > +			struct ingenic_cgu_div_info div;
> > +			struct ingenic_cgu_fixdiv_info fixdiv;
> > +		};
> > +
> > +		struct ingenic_cgu_custom_info custom;
> > +	};
> > +};
> > +
> > +/**
> > + * struct ingenic_cgu - data about the CGU
> > + * @np: the device tree node that caused the CGU to be probed
> > + * @base: the ioremap'ed base address of the CGU registers
> > + * @clock_info: an array containing information about implemented clocks
> > + * @clocks: used to provide clocks to DT, allows lookup of struct clk*
> > + * @gate_lock: lock to be held whilst (un)gating a clock

stale

> > + * @divmux_lock: lock to be held whilst re-muxing of rate-changing a clock

power_lock and pll_lock undescribed

> > + */
> > +struct ingenic_cgu {
> > +	struct device_node *np;
> > +	void __iomem *base;
> > +
> > +	const struct ingenic_cgu_clk_info *clock_info;
> > +	struct clk_onecell_data clocks;
> > +
> > +	spinlock_t divmux_lock;		/* must be held when changing a divide
> > +					   or re-muxing a clock */
> > +	spinlock_t power_lock;		/* must be held when changing a power
> > +					   manager register */
> > +	spinlock_t pll_lock;		/* must be held when changing a PLL
> > +					   control register */

those comments should go in the kernel doc description.

(Although see my previous email about locking in common clock framework).

> > +};
> > +
> > +/**
> > + * struct ingenic_clk - private data for a clock
> > + * @hw: see Documentation/clk.txt
> > + * @cgu: a pointer to the CGU data
> > + * @idx: the index of this clock in cgu->clock_info
> > + */
> > +struct ingenic_clk {
> > +	struct clk_hw hw;
> > +	struct ingenic_cgu *cgu;
> > +	unsigned idx;
> > +};
> > +
> > +#define to_ingenic_clk(_hw) container_of(_hw, struct ingenic_clk, hw)
> > +
> > +/**
> > + * ingenic_cgu_new - create a new CGU instance

function, so needs ()

> > + * @clock_info: an array of clock information structures describing the clocks
> > + *              which are implemented by the CGU
> > + * @num_clocks: the number of entries in clock_info
> > + * @np: the device tree node which causes this CGU to be probed
> > + *
> > + * Returns an opaque pointer to the CGU instance if initialisation & clock
> > + * registration is successful, otherwise NULL.

As above, do this sort of thing:
 * Return:	an opaque pointer to the CGU instance if initialisation & clock
 *		registration is successful, otherwise NULL.

> > + */
> > +struct ingenic_cgu *
> > +ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
> > +		unsigned num_clocks, struct device_node *np);
> > +
> > +/**
> > + * ingenic_cgu_register_clocks - Registers the clocks
> > + * @cgu: pointer to cgu data
> > + *
> > + * Returns 1 on success and -EINVAL if unsuccesful.

same

> > + */
> > +int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu);
> > +
> > +#endif /* __DRIVERS_CLK_INGENIC_CGU_H__ */

Nice work guys!

Cheers
James

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

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

* Re: [PATCH v3 26/37] MIPS,clk: migrate JZ4740 to common clock framework
@ 2015-04-22  9:11     ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-22  9:11 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Mike Turquette

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

On Tue, Apr 21, 2015 at 03:46:53PM +0100, Paul Burton wrote:
> Migrate the JZ4740 & the qi_lb60 board to use common clock framework
> via the new Ingenic SoC CGU driver.

Maybe worth mentioning that debugfs interface removed because common
clock framework already provides something similar.

> +static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
> +
> +	/* External clocks */
> +
> +	[JZ4740_CLK_EXT] = { "ext", CGU_CLK_EXT },
> +	[JZ4740_CLK_RTC] = { "rtc", CGU_CLK_EXT },
> +
> +	[JZ4740_CLK_PLL] = {
> +		"pll", CGU_CLK_PLL,
> +		.parents = { JZ4740_CLK_EXT, -1 },

I thought parents had 4 elements. Do the other two need initialising to -1 (and
below).

> +		.pll = {
> +			.reg = CGU_REG_CPPCR,
> +			.m_shift = 23,
> +			.m_bits = 9,
> +			.m_offset = 2,
> +			.n_shift = 18,
> +			.n_bits = 5,
> +			.n_offset = 2,
> +			.od_shift = 16,
> +			.od_bits = 2,
> +			.od_max = 4,
> +			.od_encoding = pll_od_encoding,
> +			.stable_bit = 10,
> +			.bypass_bit = 9,
> +			.enable_bit = 8,
> +		},
> +	},
> +
> +	/* Muxes & dividers */
> +
> +	[JZ4740_CLK_PLL_HALF] = {
> +		"pll half", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 21, 1, -1, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_CCLK] = {
> +		"cclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 0, 4, 22, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_HCLK] = {
> +		"hclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 4, 4, 22, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_PCLK] = {
> +		"pclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 8, 4, 22, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_MCLK] = {
> +		"mclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 12, 4, 22, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_LCD] = {
> +		"lcd", CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PLL_HALF, -1 },
> +		.div = { CGU_REG_CPCCR, 16, 5, 22, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 10 },
> +	},
> +
> +	[JZ4740_CLK_LCD_PCLK] = {
> +		"lcd_pclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL_HALF, -1 },
> +		.div = { CGU_REG_LPCDR, 0, 11, -1, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_I2S] = {
> +		"i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1 },
> +		.mux = { CGU_REG_CPCCR, 31, 1 },
> +		.div = { CGU_REG_I2SCDR, 0, 8, -1, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 6 },
> +	},
> +
> +	[JZ4740_CLK_SPI] = {
> +		"spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1 },
> +		.mux = { CGU_REG_SSICDR, 31, 1 },
> +		.div = { CGU_REG_SSICDR, 0, 4, -1, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 4 },
> +	},
> +
> +	[JZ4740_CLK_MMC] = {
> +		"mmc", CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PLL_HALF, -1 },
> +		.div = { CGU_REG_MSCCDR, 0, 5, -1, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 7 },
> +	},
> +
> +	[JZ4740_CLK_UHC] = {
> +		"uhc", CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PLL_HALF, -1 },
> +		.div = { CGU_REG_UHCCDR, 0, 4, -1, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 14 },
> +	},
> +
> +	[JZ4740_CLK_UDC] = {
> +		"udc", CGU_CLK_MUX | CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1 },
> +		.mux = { CGU_REG_CPCCR, 29, 1 },
> +		.div = { CGU_REG_CPCCR, 23, 6, -1, -1, -1 },
> +		.gate = { CGU_REG_SCR, 6 },
> +	},
> +
> +	/* Gate-only clocks */
> +
> +	[JZ4740_CLK_UART0] = {
> +		"uart0", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 0 },
> +	},
> +
> +	[JZ4740_CLK_UART1] = {
> +		"uart1", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 15 },
> +	},
> +
> +	[JZ4740_CLK_DMA] = {
> +		"dma", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PCLK, -1 },
> +		.gate = { CGU_REG_CLKGR, 12 },
> +	},
> +
> +	[JZ4740_CLK_IPU] = {
> +		"ipu", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PCLK, -1 },
> +		.gate = { CGU_REG_CLKGR, 13 },
> +	},
> +
> +	[JZ4740_CLK_ADC] = {
> +		"adc", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 8 },
> +	},
> +
> +	[JZ4740_CLK_I2C] = {
> +		"i2c", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 3 },
> +	},
> +
> +	[JZ4740_CLK_AIC] = {
> +		"aic", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 5 },
> +	},
> +};
> +
> +static void __init jz4740_cgu_init(struct device_node *np)
> +{
> +	int retval;
> +
> +	cgu = ingenic_cgu_new(jz4740_cgu_clocks,
> +			      ARRAY_SIZE(jz4740_cgu_clocks), np);
> +	if (!cgu)
> +		pr_err("%s: failed to initialise CGU\n", __func__);

return, to avoid passing NULL to ingenic_cgu_register_clocks?

> +
> +	retval = ingenic_cgu_register_clocks(cgu);
> +	if (retval)
> +		pr_err("%s: failed to register CGU Clocks\n", __func__);
> +}
> +CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);

Cheers
James

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

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

* Re: [PATCH v3 26/37] MIPS,clk: migrate JZ4740 to common clock framework
@ 2015-04-22  9:11     ` James Hogan
  0 siblings, 0 replies; 102+ messages in thread
From: James Hogan @ 2015-04-22  9:11 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, Lars-Peter Clausen, Mike Turquette

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

On Tue, Apr 21, 2015 at 03:46:53PM +0100, Paul Burton wrote:
> Migrate the JZ4740 & the qi_lb60 board to use common clock framework
> via the new Ingenic SoC CGU driver.

Maybe worth mentioning that debugfs interface removed because common
clock framework already provides something similar.

> +static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
> +
> +	/* External clocks */
> +
> +	[JZ4740_CLK_EXT] = { "ext", CGU_CLK_EXT },
> +	[JZ4740_CLK_RTC] = { "rtc", CGU_CLK_EXT },
> +
> +	[JZ4740_CLK_PLL] = {
> +		"pll", CGU_CLK_PLL,
> +		.parents = { JZ4740_CLK_EXT, -1 },

I thought parents had 4 elements. Do the other two need initialising to -1 (and
below).

> +		.pll = {
> +			.reg = CGU_REG_CPPCR,
> +			.m_shift = 23,
> +			.m_bits = 9,
> +			.m_offset = 2,
> +			.n_shift = 18,
> +			.n_bits = 5,
> +			.n_offset = 2,
> +			.od_shift = 16,
> +			.od_bits = 2,
> +			.od_max = 4,
> +			.od_encoding = pll_od_encoding,
> +			.stable_bit = 10,
> +			.bypass_bit = 9,
> +			.enable_bit = 8,
> +		},
> +	},
> +
> +	/* Muxes & dividers */
> +
> +	[JZ4740_CLK_PLL_HALF] = {
> +		"pll half", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 21, 1, -1, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_CCLK] = {
> +		"cclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 0, 4, 22, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_HCLK] = {
> +		"hclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 4, 4, 22, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_PCLK] = {
> +		"pclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 8, 4, 22, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_MCLK] = {
> +		"mclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL, -1 },
> +		.div = { CGU_REG_CPCCR, 12, 4, 22, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_LCD] = {
> +		"lcd", CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PLL_HALF, -1 },
> +		.div = { CGU_REG_CPCCR, 16, 5, 22, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 10 },
> +	},
> +
> +	[JZ4740_CLK_LCD_PCLK] = {
> +		"lcd_pclk", CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_PLL_HALF, -1 },
> +		.div = { CGU_REG_LPCDR, 0, 11, -1, -1, -1 },
> +	},
> +
> +	[JZ4740_CLK_I2S] = {
> +		"i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1 },
> +		.mux = { CGU_REG_CPCCR, 31, 1 },
> +		.div = { CGU_REG_I2SCDR, 0, 8, -1, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 6 },
> +	},
> +
> +	[JZ4740_CLK_SPI] = {
> +		"spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1 },
> +		.mux = { CGU_REG_SSICDR, 31, 1 },
> +		.div = { CGU_REG_SSICDR, 0, 4, -1, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 4 },
> +	},
> +
> +	[JZ4740_CLK_MMC] = {
> +		"mmc", CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PLL_HALF, -1 },
> +		.div = { CGU_REG_MSCCDR, 0, 5, -1, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 7 },
> +	},
> +
> +	[JZ4740_CLK_UHC] = {
> +		"uhc", CGU_CLK_DIV | CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PLL_HALF, -1 },
> +		.div = { CGU_REG_UHCCDR, 0, 4, -1, -1, -1 },
> +		.gate = { CGU_REG_CLKGR, 14 },
> +	},
> +
> +	[JZ4740_CLK_UDC] = {
> +		"udc", CGU_CLK_MUX | CGU_CLK_DIV,
> +		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1 },
> +		.mux = { CGU_REG_CPCCR, 29, 1 },
> +		.div = { CGU_REG_CPCCR, 23, 6, -1, -1, -1 },
> +		.gate = { CGU_REG_SCR, 6 },
> +	},
> +
> +	/* Gate-only clocks */
> +
> +	[JZ4740_CLK_UART0] = {
> +		"uart0", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 0 },
> +	},
> +
> +	[JZ4740_CLK_UART1] = {
> +		"uart1", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 15 },
> +	},
> +
> +	[JZ4740_CLK_DMA] = {
> +		"dma", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PCLK, -1 },
> +		.gate = { CGU_REG_CLKGR, 12 },
> +	},
> +
> +	[JZ4740_CLK_IPU] = {
> +		"ipu", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_PCLK, -1 },
> +		.gate = { CGU_REG_CLKGR, 13 },
> +	},
> +
> +	[JZ4740_CLK_ADC] = {
> +		"adc", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 8 },
> +	},
> +
> +	[JZ4740_CLK_I2C] = {
> +		"i2c", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 3 },
> +	},
> +
> +	[JZ4740_CLK_AIC] = {
> +		"aic", CGU_CLK_GATE,
> +		.parents = { JZ4740_CLK_EXT, -1 },
> +		.gate = { CGU_REG_CLKGR, 5 },
> +	},
> +};
> +
> +static void __init jz4740_cgu_init(struct device_node *np)
> +{
> +	int retval;
> +
> +	cgu = ingenic_cgu_new(jz4740_cgu_clocks,
> +			      ARRAY_SIZE(jz4740_cgu_clocks), np);
> +	if (!cgu)
> +		pr_err("%s: failed to initialise CGU\n", __func__);

return, to avoid passing NULL to ingenic_cgu_register_clocks?

> +
> +	retval = ingenic_cgu_register_clocks(cgu);
> +	if (retval)
> +		pr_err("%s: failed to register CGU Clocks\n", __func__);
> +}
> +CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);

Cheers
James

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

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

end of thread, other threads:[~2015-04-22  9:11 UTC | newest]

Thread overview: 102+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-21 14:46 [PATCH v3 00/37] JZ4780 & CI20 support Paul Burton
2015-04-21 14:46 ` Paul Burton
2015-04-21 14:46 ` Paul Burton
     [not found] ` <1429627624-30525-1-git-send-email-paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
2015-04-21 14:46   ` [PATCH v3 01/37] devicetree/bindings: add Ingenic Semiconductor vendor prefix Paul Burton
2015-04-21 14:46     ` Paul Burton
2015-04-21 14:46     ` Paul Burton
2015-04-21 14:46   ` [PATCH v3 02/37] devicetree/bindings: add Qi Hardware " Paul Burton
2015-04-21 14:46     ` Paul Burton
2015-04-21 14:46     ` Paul Burton
2015-04-21 14:46   ` [PATCH v3 10/37] devicetree: document Ingenic SoC interrupt controller binding Paul Burton
2015-04-21 14:46     ` Paul Burton
2015-04-21 14:46     ` Paul Burton
     [not found]     ` <1429627624-30525-11-git-send-email-paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
2015-04-21 16:56       ` Sergei Shtylyov
2015-04-21 16:56         ` Sergei Shtylyov
2015-04-21 14:46   ` [PATCH v3 24/37] devicetree: add Ingenic CGU binding documentation Paul Burton
2015-04-21 14:46     ` Paul Burton
2015-04-21 14:46     ` Paul Burton
     [not found]     ` <1429627624-30525-25-git-send-email-paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
2015-04-21 21:47       ` James Hogan
2015-04-21 21:47         ` James Hogan
2015-04-21 21:47         ` James Hogan
2015-04-21 14:47   ` [PATCH v3 33/37] devicetree: document Ingenic SoC UART binding Paul Burton
2015-04-21 14:47     ` Paul Burton
2015-04-21 14:47     ` Paul Burton
     [not found]     ` <1429627624-30525-34-git-send-email-paul.burton-1AXoQHu6uovQT0dZR+AlfA@public.gmane.org>
2015-04-22  4:12       ` Rob Herring
2015-04-22  4:12         ` Rob Herring
2015-04-21 14:54   ` [PATCH v3 00/37] JZ4780 & CI20 support Paul Burton
2015-04-21 14:54     ` Paul Burton
2015-04-21 14:54     ` Paul Burton
2015-04-22  4:06   ` Rob Herring
2015-04-22  4:06     ` Rob Herring
2015-04-21 14:46 ` [PATCH v3 03/37] MIPS: JZ4740: introduce CONFIG_MACH_INGENIC Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 04/37] MIPS: ingenic: add newer vendor IDs Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 05/37] MIPS: JZ4740: require & include DT Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 06/37] MIPS: irq_cpu: declare irqchip table entry Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 07/37] MIPS: JZ4740: probe CPU interrupt controller via DT Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 08/37] MIPS: JZ4740: use generic plat_irq_dispatch Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 09/37] MIPS: JZ4740: move arch_init_irq out of arch/mips/jz4740/irq.c Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 11/37] MIPS: JZ4740: probe interrupt controller via DT Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 12/37] MIPS: JZ4740: parse SoC interrupt controller parent IRQ from DT Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 13/37] MIPS: JZ4740: register an irq_domain for the interrupt controller Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 14/37] MIPS: JZ4740: drop intc debugfs code Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 15/37] MIPS: JZ4740: remove jz_intc_base global Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 21:09   ` James Hogan
2015-04-21 21:09     ` James Hogan
2015-04-21 14:46 ` [PATCH v3 16/37] MIPS: JZ4740: support >32 interrupts Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 17/37] MIPS: JZ4740: define IRQ numbers based on number of intc IRQs Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 18/37] MIPS: JZ4740: read intc base address from DT Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 19/37] MIPS: JZ4740: avoid JZ4740-specific naming Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 20/37] MIPS: JZ4740: support newer SoC interrupt controllers Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 21/37] irqchip: move Ingenic SoC intc driver to drivers/irqchip Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 22/37] MIPS: JZ4740: call jz4740_clock_init earlier Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 23/37] MIPS: JZ4740: replace use of jz4740_clock_bdata Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 25/37] clk: ingenic: add driver for Ingenic SoC CGU clocks Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 23:25   ` James Hogan
2015-04-21 23:25     ` James Hogan
2015-04-22  8:52     ` James Hogan
2015-04-22  8:52       ` James Hogan
2015-04-21 14:46 ` [PATCH v3 26/37] MIPS,clk: migrate JZ4740 to common clock framework Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-22  9:11   ` James Hogan
2015-04-22  9:11     ` James Hogan
2015-04-21 14:46 ` [PATCH v3 27/37] MIPS,clk: move jz4740_clock_set_wait_mode to jz4740-cgu Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 28/37] MIPS,clk: move jz4740 UDC auto suspend functions " Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 29/37] MIPS,clk: move jz4740 clock suspend,resume " Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 30/37] clk: ingenic: add JZ4780 CGU support Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 31/37] MIPS: JZ4740: remove clock.h Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:46 ` [PATCH v3 32/37] MIPS: JZ4740: only detect RAM size if not specified in DT Paul Burton
2015-04-21 14:46   ` Paul Burton
2015-04-21 14:47 ` [PATCH v3 34/37] serial: 8250_ingenic: support for Ingenic SoC UARTs Paul Burton
2015-04-21 14:47   ` Paul Burton
2015-04-21 14:47 ` [PATCH v3 35/37] MIPS: JZ4740: use Ingenic SoC UART driver Paul Burton
2015-04-21 14:47   ` Paul Burton
2015-04-21 14:47 ` [PATCH v3 36/37] MIPS: ingenic: initial JZ4780 support Paul Burton
2015-04-21 14:47   ` Paul Burton
2015-04-21 14:47 ` [PATCH v3 37/37] MIPS: ingenic: initial MIPS Creator CI20 support Paul Burton
2015-04-21 14:47   ` Paul Burton

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.