Changes between http://archive.arm.linux.org.uk/lurker/message/20130408.113343.585af217.en.html and v2:
* Added new drivers to support the irqchip and timers on older models.
* Added new device trees to support the other models.
Changes between v2 and v3:
* Clean up keypad driver
* Update copyright messages (2012->2013)
* Added clock driver
* Fix keypad support for classic models
* Fix nspire-classic-timer code to use updated CLOCKSOURCE_OF_DECLARE
* Change CLCD code to use panel capabilities
* Change UART clock to match APB speed
* Support for reset
Changes between v3 and v4:
* Remove redundant clock-names in device tree
* Re-enable bus access to some peripherals on bootup
* Clean up nspire-classic-timer code.
- Implement a nspire_timer_set_mode function
- Removed messy IO_MATCHx and CNTL_MATCHx macros
- Timer starts disabled to begin with
- Interrupt handling code return IRQ_NONE for spurious interrupts
- Delete unnessecary shift
* Change clk-nspire to use compatible property to determine IO type
* Change device tree bindings to have appropriate vendor prefixes
* Added device tree binding documentation
* Fix incorrect register addresses for clocks
* Use more specific .caps for CLCD
Daniel Tang (6):
arm: TI-Nspire platform code
arm: TI-Nspire device trees
clk: TI-Nspire clock drivers
clocksource: TI-Nspire timer support
input: TI-Nspire keypad support
irqchip: TI-Nspire irqchip support
.../devicetree/bindings/clock/nspire-clock.txt | 24 ++
.../devicetree/bindings/input/ti,nspire-keypad.txt | 60 ++++
.../interrupt-controller/lsi,zevio-intc.txt | 18 ++
.../devicetree/bindings/timer/lsi,zevio-timer.txt | 33 +++
.../devicetree/bindings/vendor-prefixes.txt | 1 +
arch/arm/Kconfig | 2 +
arch/arm/Kconfig.debug | 16 ++
arch/arm/Makefile | 1 +
arch/arm/boot/dts/Makefile | 3 +
arch/arm/boot/dts/nspire-classic.dtsi | 74 +++++
arch/arm/boot/dts/nspire-clp.dts | 45 +++
arch/arm/boot/dts/nspire-cx.dts | 112 ++++++++
arch/arm/boot/dts/nspire-tp.dts | 44 +++
arch/arm/boot/dts/nspire.dtsi | 175 ++++++++++++
arch/arm/include/debug/nspire.S | 28 ++
arch/arm/mach-nspire/Kconfig | 15 +
arch/arm/mach-nspire/Makefile | 2 +
arch/arm/mach-nspire/Makefile.boot | 0
arch/arm/mach-nspire/clcd.c | 119 ++++++++
arch/arm/mach-nspire/clcd.h | 14 +
arch/arm/mach-nspire/mmio.h | 23 ++
arch/arm/mach-nspire/nspire.c | 117 ++++++++
drivers/clk/Makefile | 1 +
drivers/clk/clk-nspire.c | 155 ++++++++++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/zevio-timer.c | 231 +++++++++++++++
drivers/input/keyboard/Kconfig | 10 +
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/nspire-keypad.c | 315 +++++++++++++++++++++
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-zevio.c | 177 ++++++++++++
31 files changed, 1818 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/nspire-clock.txt
create mode 100644 Documentation/devicetree/bindings/input/ti,nspire-keypad.txt
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt
create mode 100644 Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt
create mode 100644 arch/arm/boot/dts/nspire-classic.dtsi
create mode 100644 arch/arm/boot/dts/nspire-clp.dts
create mode 100644 arch/arm/boot/dts/nspire-cx.dts
create mode 100644 arch/arm/boot/dts/nspire-tp.dts
create mode 100644 arch/arm/boot/dts/nspire.dtsi
create mode 100644 arch/arm/include/debug/nspire.S
create mode 100644 arch/arm/mach-nspire/Kconfig
create mode 100644 arch/arm/mach-nspire/Makefile
create mode 100644 arch/arm/mach-nspire/Makefile.boot
create mode 100644 arch/arm/mach-nspire/clcd.c
create mode 100644 arch/arm/mach-nspire/clcd.h
create mode 100644 arch/arm/mach-nspire/mmio.h
create mode 100644 arch/arm/mach-nspire/nspire.c
create mode 100644 drivers/clk/clk-nspire.c
create mode 100644 drivers/clocksource/zevio-timer.c
create mode 100644 drivers/input/keyboard/nspire-keypad.c
create mode 100644 drivers/irqchip/irq-zevio.c
--
1.8.1.3
Include device trees for the TI-Nspire.
Signed-off-by: Daniel Tang <[email protected]>
---
.../devicetree/bindings/vendor-prefixes.txt | 1 +
arch/arm/boot/dts/Makefile | 3 +
arch/arm/boot/dts/nspire-classic.dtsi | 74 +++++++++
arch/arm/boot/dts/nspire-clp.dts | 45 ++++++
arch/arm/boot/dts/nspire-cx.dts | 112 +++++++++++++
arch/arm/boot/dts/nspire-tp.dts | 44 ++++++
arch/arm/boot/dts/nspire.dtsi | 175 +++++++++++++++++++++
7 files changed, 454 insertions(+)
create mode 100644 arch/arm/boot/dts/nspire-classic.dtsi
create mode 100644 arch/arm/boot/dts/nspire-clp.dts
create mode 100644 arch/arm/boot/dts/nspire-cx.dts
create mode 100644 arch/arm/boot/dts/nspire-tp.dts
create mode 100644 arch/arm/boot/dts/nspire.dtsi
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 6931c43..b27b057 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -31,6 +31,7 @@ idt Integrated Device Technologies, Inc.
img Imagination Technologies Ltd.
intercontrol Inter Control Group
linux Linux-specific binding
+lsi LSI Corp. (LSI Logic)
marvell Marvell Technology Group Ltd.
maxim Maxim Integrated Products
mosaixtech Mosaix Technologies, Inc.
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index b9f7121..5677d6c 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -135,6 +135,9 @@ dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
imx28-sps1.dtb \
imx28-tx28.dtb
dtb-$(CONFIG_ARCH_NOMADIK) += ste-nomadik-s8815.dtb
+dtb-$(CONFIG_ARCH_NSPIRE) += nspire-cx.dtb \
+ nspire-tp.dtb \
+ nspire-clp.dtb
dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
omap3430-sdp.dtb \
omap3-beagle.dtb \
diff --git a/arch/arm/boot/dts/nspire-classic.dtsi b/arch/arm/boot/dts/nspire-classic.dtsi
new file mode 100644
index 0000000..9565199
--- /dev/null
+++ b/arch/arm/boot/dts/nspire-classic.dtsi
@@ -0,0 +1,74 @@
+/*
+ * linux/arch/arm/boot/nspire-classic.dts
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/include/ "nspire.dtsi"
+
+&lcd {
+ lcd-type = "classic";
+};
+
+&fast_timer {
+ /* compatible = "lsi,zevio-timer"; */
+ reg = <0x90010000 0x1000>, <0x900A0010 0x8>;
+};
+
+&uart {
+ compatible = "ns16550";
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&apb_pclk>;
+ no-loopback-test;
+};
+
+&timer0 {
+ /* compatible = "lsi,zevio-timer"; */
+ reg = <0x900C0000 0x1000>, <0x900A0018 0x8>;
+};
+
+&timer1 {
+ compatible = "lsi,zevio-timer";
+ reg = <0x900D0000 0x1000>, <0x900A0020 0x8>;
+};
+
+&keypad {
+ active-low;
+
+};
+
+&base_clk {
+ compatible = "lsi,nspire-classic-clock";
+};
+
+&ahb_clk {
+ compatible = "lsi,nspire-classic-ahb-divider";
+};
+
+/ {
+ memory {
+ device_type = "memory";
+ reg = <0x10000000 0x2000000>; /* 32 MB */
+ };
+
+ ahb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ intc: interrupt-controller@DC000000 {
+ compatible = "lsi,zevio-intc";
+ interrupt-controller;
+ reg = <0xDC000000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+ };
+ chosen {
+ bootargs = "debug earlyprintk console=tty0 console=ttyS0,115200n8 root=/dev/ram0";
+ };
+};
diff --git a/arch/arm/boot/dts/nspire-clp.dts b/arch/arm/boot/dts/nspire-clp.dts
new file mode 100644
index 0000000..3f9c8af
--- /dev/null
+++ b/arch/arm/boot/dts/nspire-clp.dts
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/arm/boot/nspire-clp.dts
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+
+/include/ "nspire-classic.dtsi"
+
+&keypad {
+ keymap = <
+ 0x0000001c 0x0001001c 0x00020039
+ 0x0004002c 0x00050034 0x00060015
+ 0x0007000b 0x0008002d 0x01000033
+ 0x0101004e 0x01020011 0x01030004
+ 0x0104002f 0x01050003 0x01060016
+ 0x01070002 0x01080014 0x02000062
+ 0x0201000c 0x0202001f 0x02030007
+ 0x02040013 0x02050006 0x02060010
+ 0x02070005 0x02080019 0x03000027
+ 0x03010037 0x03020018 0x0303000a
+ 0x03040031 0x03050009 0x03060032
+ 0x03070008 0x03080026 0x04000028
+ 0x04010035 0x04020025 0x04040024
+ 0x04060017 0x04080023 0x05000028
+ 0x05020022 0x0503001b 0x05040021
+ 0x0505001a 0x05060012 0x0507006f
+ 0x05080020 0x0509002a 0x0601001c
+ 0x0602002e 0x06030068 0x06040030
+ 0x0605006d 0x0606001e 0x06070001
+ 0x0608002b 0x0609000f 0x07000067
+ 0x0702006a 0x0704006c 0x07060069
+ 0x0707000e 0x0708001d 0x070a000d
+ >;
+};
+
+/ {
+ model = "TI-NSPIRE Clickpad";
+ compatible = "ti,nspire-clp";
+};
diff --git a/arch/arm/boot/dts/nspire-cx.dts b/arch/arm/boot/dts/nspire-cx.dts
new file mode 100644
index 0000000..64632ca
--- /dev/null
+++ b/arch/arm/boot/dts/nspire-cx.dts
@@ -0,0 +1,112 @@
+/*
+ * linux/arch/arm/boot/nspire-cx.dts
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+
+/include/ "nspire.dtsi"
+
+&lcd {
+ lcd-type = "cx";
+};
+
+&fast_timer {
+ /* compatible = "arm,sp804", "arm,primecell"; */
+};
+
+&uart {
+ compatible = "arm,pl011", "arm,primecell";
+
+ clocks = <&uart_clk>, <&apb_pclk>;
+ clock-names = "uart_clk", "apb_pclk";
+};
+
+&timer0 {
+ compatible = "arm,sp804", "arm,primecell";
+};
+
+&timer1 {
+ compatible = "arm,sp804", "arm,primecell";
+};
+
+&base_clk {
+ compatible = "lsi,nspire-cx-clock";
+};
+
+&ahb_clk {
+ compatible = "lsi,nspire-cx-ahb-divider";
+};
+
+&keypad {
+ keymap = <
+ 0x0000001c 0x0001001c 0x00040039
+ 0x0005002c 0x00060015 0x0007000b
+ 0x0008000f 0x0100002d 0x01010011
+ 0x0102002f 0x01030004 0x01040016
+ 0x01050014 0x0106001f 0x01070002
+ 0x010a006a 0x02000013 0x02010010
+ 0x02020019 0x02030007 0x02040018
+ 0x02050031 0x02060032 0x02070005
+ 0x02080028 0x0209006c 0x03000026
+ 0x03010025 0x03020024 0x0303000a
+ 0x03040017 0x03050023 0x03060022
+ 0x03070008 0x03080035 0x03090069
+ 0x04000021 0x04010012 0x04020020
+ 0x0404002e 0x04050030 0x0406001e
+ 0x0407000d 0x04080037 0x04090067
+ 0x05010038 0x0502000c 0x0503001b
+ 0x05040034 0x0505001a 0x05060006
+ 0x05080027 0x0509000e 0x050a006f
+ 0x0600002b 0x0602004e 0x06030068
+ 0x06040003 0x0605006d 0x06060009
+ 0x06070001 0x0609000f 0x0708002a
+ 0x0709001d 0x070a0033 >;
+};
+
+/ {
+ model = "TI-NSPIRE CX";
+ compatible = "ti,nspire-cx";
+
+ memory {
+ device_type = "memory";
+ reg = <0x10000000 0x4000000>; /* 64 MB */
+ };
+
+ uart_clk: uart_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <12000000>;
+ };
+
+ ahb {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ intc: interrupt-controller@DC000000 {
+ compatible = "arm,pl190-vic";
+ interrupt-controller;
+ reg = <0xDC000000 0x1000>;
+ #interrupt-cells = <1>;
+ };
+
+ apb@90000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ i2c@90050000 {
+ compatible = "snps,designware-i2c";
+ reg = <0x90050000 0x1000>;
+ interrupts = <20>;
+ };
+ };
+ };
+ chosen {
+ bootargs = "debug earlyprintk console=tty0 console=ttyAMA0,115200n8 root=/dev/ram0";
+ };
+};
diff --git a/arch/arm/boot/dts/nspire-tp.dts b/arch/arm/boot/dts/nspire-tp.dts
new file mode 100644
index 0000000..ab209a3
--- /dev/null
+++ b/arch/arm/boot/dts/nspire-tp.dts
@@ -0,0 +1,44 @@
+/*
+ * linux/arch/arm/boot/nspire-tp.dts
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+/dts-v1/;
+
+/include/ "nspire-classic.dtsi"
+
+&keypad {
+ keymap = <
+ 0x0000001c 0x0001001c 0x00040039
+ 0x0005002c 0x00060015 0x0007000b
+ 0x0008000f 0x0100002d 0x01010011
+ 0x0102002f 0x01030004 0x01040016
+ 0x01050014 0x0106001f 0x01070002
+ 0x010a006a 0x02000013 0x02010010
+ 0x02020019 0x02030007 0x02040018
+ 0x02050031 0x02060032 0x02070005
+ 0x02080028 0x0209006c 0x03000026
+ 0x03010025 0x03020024 0x0303000a
+ 0x03040017 0x03050023 0x03060022
+ 0x03070008 0x03080035 0x03090069
+ 0x04000021 0x04010012 0x04020020
+ 0x0404002e 0x04050030 0x0406001e
+ 0x0407000d 0x04080037 0x04090067
+ 0x05010038 0x0502000c 0x0503001b
+ 0x05040034 0x0505001a 0x05060006
+ 0x05080027 0x0509000e 0x050a006f
+ 0x0600002b 0x0602004e 0x06030068
+ 0x06040003 0x0605006d 0x06060009
+ 0x06070001 0x0609000f 0x0708002a
+ 0x0709001d 0x070a0033 >;
+};
+
+/ {
+ model = "TI-NSPIRE Touchpad";
+ compatible = "ti,nspire-tp";
+};
diff --git a/arch/arm/boot/dts/nspire.dtsi b/arch/arm/boot/dts/nspire.dtsi
new file mode 100644
index 0000000..a22ffe6
--- /dev/null
+++ b/arch/arm/boot/dts/nspire.dtsi
@@ -0,0 +1,175 @@
+/*
+ * linux/arch/arm/boot/nspire.dtsi
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ interrupt-parent = <&intc>;
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,arm926ejs";
+ };
+ };
+
+ bootrom: bootrom@00000000 {
+ reg = <0x00000000 0x80000>;
+ };
+
+ sram: sram@A4000000 {
+ device = "memory";
+ reg = <0xA4000000 0x20000>;
+ };
+
+ timer_clk: timer_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ };
+
+ base_clk: base_clk {
+ #clock-cells = <0>;
+ reg = <0x900B0024 0x4>;
+ };
+
+ ahb_clk: ahb_clk {
+ #clock-cells = <0>;
+ reg = <0x900B0024 0x4>;
+ clocks = <&base_clk>;
+ };
+
+ apb_pclk: apb_pclk {
+ #clock-cells = <0>;
+ compatible = "fixed-factor-clock";
+ clock-div = <2>;
+ clock-mult = <1>;
+ clocks = <&ahb_clk>;
+ };
+
+ ahb {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ spi: spi@A9000000 {
+ reg = <0xA9000000 0x1000>;
+ };
+
+ usb0: usb@B0000000 {
+ reg = <0xB0000000 0x1000>;
+ interrupts = <8>;
+ };
+
+ usb1: usb@B4000000 {
+ reg = <0xB4000000 0x1000>;
+ interrupts = <9>;
+ status = "disabled";
+ };
+
+ lcd: lcd@C0000000 {
+ compatible = "arm,pl111", "arm,primecell";
+ reg = <0xC0000000 0x1000>;
+ interrupts = <21>;
+
+ clocks = <&apb_pclk>;
+ clock-names = "apb_pclk";
+ };
+
+ adc: adc@C4000000 {
+ reg = <0xC4000000 0x1000>;
+ interrupts = <11>;
+ };
+
+ tdes: crypto@C8010000 {
+ reg = <0xC8010000 0x1000>;
+ };
+
+ sha256: crypto@CC000000 {
+ reg = <0xCC000000 0x1000>;
+ };
+
+ apb@90000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clock-ranges;
+ ranges;
+
+ gpio: gpio@90000000 {
+ reg = <0x90000000 0x1000>;
+ interrupts = <7>;
+ };
+
+ fast_timer: timer@90010000 {
+ reg = <0x90010000 0x1000>;
+ interrupts = <17>;
+ };
+
+ uart: serial@90020000 {
+ reg = <0x90020000 0x1000>;
+ interrupts = <1>;
+ };
+
+ timer0: timer@900C0000 {
+ reg = <0x900C0000 0x1000>;
+
+ clocks = <&timer_clk>;
+ };
+
+ timer1: timer@900D0000 {
+ reg = <0x900D0000 0x1000>;
+ interrupts = <19>;
+
+ clocks = <&timer_clk>;
+ };
+
+ watchdog: watchdog@90060000 {
+ compatible = "arm,amba-primecell";
+ reg = <0x90060000 0x1000>;
+ interrupts = <3>;
+ };
+
+ rtc: rtc@90090000 {
+ reg = <0x90090000 0x1000>;
+ interrupts = <4>;
+ };
+
+ misc: misc@900A0000 {
+ reg = <0x900A0000 0x1000>;
+ };
+
+ pwr: pwr@900B0000 {
+ reg = <0x900B0000 0x1000>;
+ interrupts = <15>;
+ };
+
+ keypad: input@900E0000 {
+ compatible = "ti,nspire-keypad";
+ reg = <0x900E0000 0x1000>;
+ interrupts = <16>;
+
+ scan-interval = <1000>;
+ row-delay = <200>;
+
+ clocks = <&apb_pclk>;
+ };
+
+ contrast: contrast@900F0000 {
+ reg = <0x900F0000 0x1000>;
+ };
+
+ led: led@90110000 {
+ reg = <0x90110000 0x1000>;
+ };
+ };
+ };
+};
--
1.8.1.3
Add support for TI-Nspire clocks.
Signed-off-by: Daniel Tang <[email protected]>
---
.../devicetree/bindings/clock/nspire-clock.txt | 24 ++++
drivers/clk/Makefile | 1 +
drivers/clk/clk-nspire.c | 155 +++++++++++++++++++++
3 files changed, 180 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/nspire-clock.txt
create mode 100644 drivers/clk/clk-nspire.c
diff --git a/Documentation/devicetree/bindings/clock/nspire-clock.txt b/Documentation/devicetree/bindings/clock/nspire-clock.txt
new file mode 100644
index 0000000..7c3bc8b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nspire-clock.txt
@@ -0,0 +1,24 @@
+TI-NSPIRE Clocks
+
+Required properties:
+- compatible: Valid compatible properties include:
+ "lsi,nspire-cx-ahb-divider" for the AHB divider in the CX model
+ "lsi,nspire-classic-ahb-divider" for the AHB divider in the older model
+ "lsi,nspire-cx-clock" for the base clock in the CX model
+ "lsi,nspire-classic-clock" for the base clock in the older model
+
+- reg: Physical base address of the controller and length of memory mapped
+ region.
+
+Optional:
+- clocks: For the "nspire-*-ahb-divider" compatible clocks, this is the parent
+ clock where it divides the rate from.
+
+Example:
+
+ahb_clk {
+ #clock-cells = <0>;
+ compatible = "lsi,nspire-cx-clock";
+ reg = <0x900B0000 0x4>;
+ clocks = <&base_clk>;
+};
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 137d3e7..72ebbe1 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-composite.o
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
+obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
obj-$(CONFIG_ARCH_MXS) += mxs/
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
obj-$(CONFIG_PLAT_SPEAR) += spear/
diff --git a/drivers/clk/clk-nspire.c b/drivers/clk/clk-nspire.c
new file mode 100644
index 0000000..2546f7d
--- /dev/null
+++ b/drivers/clk/clk-nspire.c
@@ -0,0 +1,155 @@
+/*
+ * linux/drivers/clk/clk-nspire.c
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define MHZ (1000 * 1000)
+
+#define BASE_CPU_SHIFT 1
+#define BASE_CPU_MASK 0x7F
+
+#define CPU_AHB_SHIFT 12
+#define CPU_AHB_MASK 0x07
+
+#define FIXED_BASE_SHIFT 8
+#define FIXED_BASE_MASK 0x01
+
+#define CLASSIC_BASE_SHIFT 16
+#define CLASSIC_BASE_MASK 0x1F
+
+#define CX_BASE_SHIFT 15
+#define CX_BASE_MASK 0x3F
+
+#define CX_UNKNOWN_SHIFT 21
+#define CX_UNKNOWN_MASK 0x03
+
+struct nspire_clk_info {
+ u32 base_clock;
+ u16 base_cpu_ratio;
+ u16 base_ahb_ratio;
+};
+
+
+#define EXTRACT(var, prop) (((var)>>prop##_SHIFT) & prop##_MASK)
+static void nspire_clkinfo_cx(u32 val, struct nspire_clk_info *clk)
+{
+ if (EXTRACT(val, FIXED_BASE))
+ clk->base_clock = 48 * MHZ;
+ else
+ clk->base_clock = 6 * EXTRACT(val, CX_BASE) * MHZ;
+
+ clk->base_cpu_ratio = EXTRACT(val, BASE_CPU) * EXTRACT(val, CX_UNKNOWN);
+ clk->base_ahb_ratio = clk->base_cpu_ratio * (EXTRACT(val, CPU_AHB) + 1);
+}
+
+static void nspire_clkinfo_classic(u32 val, struct nspire_clk_info *clk)
+{
+ if (EXTRACT(val, FIXED_BASE))
+ clk->base_clock = 27 * MHZ;
+ else
+ clk->base_clock = (300 - 6 * EXTRACT(val, CLASSIC_BASE)) * MHZ;
+
+ clk->base_cpu_ratio = EXTRACT(val, BASE_CPU) * 2;
+ clk->base_ahb_ratio = clk->base_cpu_ratio * (EXTRACT(val, CPU_AHB) + 1);
+}
+#undef EXTRACT
+
+static void __init nspire_ahbdiv_setup(struct device_node *node,
+ void (*get_clkinfo)(u32, struct nspire_clk_info *))
+{
+ u32 val;
+ void __iomem *io;
+ struct clk *clk;
+ const char *clk_name = node->name;
+ const char *parent_name;
+ struct nspire_clk_info info;
+
+ io = of_iomap(node, 0);
+ if (!io)
+ return;
+ val = readl(io);
+ iounmap(io);
+
+ get_clkinfo(val, &info);
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+ parent_name = of_clk_get_parent_name(node, 0);
+
+ clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0,
+ 1, info.base_ahb_ratio);
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+static void __init nspire_ahbdiv_setup_cx(struct device_node *node)
+{
+ nspire_ahbdiv_setup(node, nspire_clkinfo_cx);
+}
+
+static void __init nspire_ahbdiv_setup_classic(struct device_node *node)
+{
+ nspire_ahbdiv_setup(node, nspire_clkinfo_classic);
+}
+
+CLK_OF_DECLARE(nspire_ahbdiv_cx, "lsi,nspire-cx-ahb-divider",
+ nspire_ahbdiv_setup_cx);
+CLK_OF_DECLARE(nspire_ahbdiv_classic, "lsi,nspire-classic-ahb-divider",
+ nspire_ahbdiv_setup_classic);
+
+static void __init nspire_clk_setup(struct device_node *node,
+ void (*get_clkinfo)(u32, struct nspire_clk_info *))
+{
+ u32 val;
+ void __iomem *io;
+ struct clk *clk;
+ const char *clk_name = node->name;
+ struct nspire_clk_info info;
+
+ io = of_iomap(node, 0);
+ if (!io)
+ return;
+ val = readl(io);
+ iounmap(io);
+
+ get_clkinfo(val, &info);
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT,
+ info.base_clock);
+ if (!IS_ERR(clk))
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ else
+ return;
+
+ pr_info("TI-NSPIRE Base: %uMHz CPU: %uMHz AHB: %uMHz\n",
+ info.base_clock / MHZ,
+ info.base_clock / info.base_cpu_ratio / MHZ,
+ info.base_clock / info.base_ahb_ratio / MHZ);
+}
+
+static void __init nspire_clk_setup_cx(struct device_node *node)
+{
+ nspire_clk_setup(node, nspire_clkinfo_cx);
+}
+
+static void __init nspire_clk_setup_classic(struct device_node *node)
+{
+ nspire_clk_setup(node, nspire_clkinfo_classic);
+}
+
+CLK_OF_DECLARE(nspire_clk_cx, "lsi,nspire-cx-clock", nspire_clk_setup_cx);
+CLK_OF_DECLARE(nspire_clk_classic, "lsi,nspire-classic-clock",
+ nspire_clk_setup_classic);
--
1.8.1.3
Add clocksource and clockevent driver for the TI-Nspire.
Signed-off-by: Daniel Tang <[email protected]>
---
.../devicetree/bindings/timer/lsi,zevio-timer.txt | 33 +++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/zevio-timer.c | 231 +++++++++++++++++++++
3 files changed, 265 insertions(+)
create mode 100644 Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt
create mode 100644 drivers/clocksource/zevio-timer.c
diff --git a/Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt b/Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt
new file mode 100644
index 0000000..b2d07ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt
@@ -0,0 +1,33 @@
+TI-NSPIRE timer
+
+Required properties:
+
+- compatible : should be "lsi,zevio-timer".
+- reg : The physical base address and size of the timer (always first).
+- clocks: phandle to the source clock.
+
+Optional properties:
+
+- interrupts : The interrupt number of the first timer.
+- reg : The interrupt acknowledgement registers
+ (always after timer base address)
+
+If any of the optional properties are not given, the timer is added as a
+clock-source only.
+
+Example:
+
+timer {
+ compatible = "lsi,zevio-timer";
+ reg = <0x900D0000 0x1000>, <0x900A0020 0x8>;
+ interrupts = <19>;
+ clocks = <&timer_clk>;
+};
+
+Example (no clock-events):
+
+timer {
+ compatible = "lsi,zevio-timer";
+ reg = <0x900D0000 0x1000>;
+ clocks = <&timer_clk>;
+};
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 8d979c7..293f86e 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o
obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o
obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
+obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o
obj-$(CONFIG_ARCH_BCM) += bcm_kona_timer.o
obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o
obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c
new file mode 100644
index 0000000..c6d7f03
--- /dev/null
+++ b/drivers/clocksource/zevio-timer.c
@@ -0,0 +1,231 @@
+/*
+ * linux/drivers/clocksource/zevio-timer.c
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+#define IO_CURRENT_VAL 0x00
+#define IO_DIVIDER 0x04
+#define IO_CONTROL 0x08
+
+#define IO_TIMER1 0x00
+#define IO_TIMER2 0x0C
+
+#define IO_MATCH_BEGIN 0x18
+#define IO_MATCH(x) (IO_MATCH_BEGIN + ((x)<<2))
+
+#define IO_INTR_STS 0x00
+#define IO_INTR_ACK 0x00
+#define IO_INTR_MSK 0x04
+
+#define CNTL_STOP_TIMER (1<<4)
+#define CNTL_RUN_TIMER (0<<4)
+
+#define CNTL_INC (1<<3)
+#define CNTL_DEC (0<<3)
+
+#define CNTL_TOZERO 0
+#define CNTL_MATCH(x) ((x) + 1)
+#define CNTL_FOREVER 7
+
+/* There are 6 match registers but we only use one. */
+#define TIMER_MATCH 0
+
+#define TIMER_INTR_MSK (1<<(TIMER_MATCH))
+#define TIMER_INTR_ALL 0x3F
+
+struct zevio_timer {
+ void __iomem *base;
+ void __iomem *timer1, *timer2;
+ void __iomem *interrupt_regs;
+
+ int irqnr;
+
+ struct clk *clk;
+ struct clock_event_device clkevt;
+ struct irqaction clkevt_irq;
+
+ char clocksource_name[64];
+ char clockevent_name[64];
+};
+
+static int zevio_timer_set_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ unsigned long flags;
+ struct zevio_timer *timer = container_of(dev,
+ struct zevio_timer,
+ clkevt);
+
+ local_irq_save(flags);
+
+ writel(delta, timer->timer1 + IO_CURRENT_VAL);
+ writel(CNTL_RUN_TIMER | CNTL_DEC | CNTL_MATCH(TIMER_MATCH),
+ timer->timer1 + IO_CONTROL);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static void zevio_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *dev)
+{
+ unsigned long flags;
+ struct zevio_timer *timer = container_of(dev,
+ struct zevio_timer,
+ clkevt);
+
+ local_irq_save(flags);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* Unsupported */
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* Enable timer interrupts */
+ writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK);
+ writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
+ dev->mode = mode;
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ /* Disable timer interrupts */
+ writel(0, timer->interrupt_regs + IO_INTR_MSK);
+ writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
+ /* Stop timer */
+ writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);
+ dev->mode = mode;
+ break;
+ }
+
+ local_irq_restore(flags);
+}
+
+static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id)
+{
+ struct zevio_timer *timer = dev_id;
+ u32 intr;
+
+ intr = readl(timer->interrupt_regs + IO_INTR_ACK);
+ if (!(intr & TIMER_INTR_MSK))
+ return IRQ_NONE;
+
+ writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_ACK);
+ writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);
+
+ if (timer->clkevt.event_handler)
+ timer->clkevt.event_handler(&timer->clkevt);
+
+ return IRQ_HANDLED;
+}
+
+static int __init zevio_timer_add(struct device_node *node)
+{
+ struct zevio_timer *timer;
+ struct resource res;
+ int ret;
+
+ timer = kzalloc(sizeof(*timer), GFP_ATOMIC);
+ if (!timer)
+ return -ENOMEM;
+
+ timer->base = of_iomap(node, 0);
+ if (!timer->base) {
+ ret = -EINVAL;
+ goto error_free;
+ }
+ timer->timer1 = timer->base + IO_TIMER1;
+ timer->timer2 = timer->base + IO_TIMER2;
+
+ timer->clk = of_clk_get(node, 0);
+ if (IS_ERR(timer->clk)) {
+ ret = PTR_ERR(timer->clk);
+ pr_err("Timer clock not found! (error %d)\n", ret);
+ goto error_unmap;
+ }
+
+ timer->interrupt_regs = of_iomap(node, 1);
+ timer->irqnr = irq_of_parse_and_map(node, 0);
+
+ of_address_to_resource(node, 0, &res);
+ scnprintf(timer->clocksource_name, sizeof(timer->clocksource_name),
+ "%llx.%s_clocksource",
+ (unsigned long long)res.start, node->name);
+
+ scnprintf(timer->clockevent_name, sizeof(timer->clockevent_name),
+ "%llx.%s_clockevent",
+ (unsigned long long)res.start, node->name);
+
+ if (timer->interrupt_regs && timer->irqnr) {
+ timer->clkevt.name = timer->clockevent_name;
+ timer->clkevt.set_next_event = zevio_timer_set_event;
+ timer->clkevt.set_mode = zevio_timer_set_mode;
+ timer->clkevt.rating = 200;
+ timer->clkevt.cpumask = cpu_all_mask;
+ timer->clkevt.features =
+ CLOCK_EVT_FEAT_ONESHOT;
+
+ writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);
+ writel(0, timer->timer1 + IO_DIVIDER);
+
+ /* Start with timer interrupts disabled */
+ writel(0, timer->interrupt_regs + IO_INTR_MSK);
+ writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
+
+ /* Interrupt to occur when timer value matches 0 */
+ writel(0, timer->base + IO_MATCH(TIMER_MATCH));
+
+ timer->clkevt_irq.name = timer->clockevent_name;
+ timer->clkevt_irq.handler = zevio_timer_interrupt;
+ timer->clkevt_irq.dev_id = timer;
+ timer->clkevt_irq.flags =
+ IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL;
+
+ setup_irq(timer->irqnr, &timer->clkevt_irq);
+
+ clockevents_config_and_register(&timer->clkevt,
+ clk_get_rate(timer->clk), 0x0001, 0xffff);
+ pr_info("Added %s as clockevent\n", timer->clockevent_name);
+ }
+
+ writel(CNTL_STOP_TIMER, timer->timer2 + IO_CONTROL);
+ writel(0, timer->timer2 + IO_CURRENT_VAL);
+ writel(0, timer->timer2 + IO_DIVIDER);
+ writel(CNTL_RUN_TIMER | CNTL_FOREVER | CNTL_INC,
+ timer->timer2 + IO_CONTROL);
+
+ clocksource_mmio_init(timer->timer2 + IO_CURRENT_VAL,
+ timer->clocksource_name,
+ clk_get_rate(timer->clk),
+ 200, 16,
+ clocksource_mmio_readw_up);
+
+ pr_info("Added %s as clocksource\n", timer->clocksource_name);
+
+ return 0;
+error_unmap:
+ iounmap(timer->base);
+error_free:
+ kfree(timer);
+ return ret;
+}
+
+CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_add);
--
1.8.1.3
Add support for the built-in keypad on TI-Nspires.
Signed-off-by: Daniel Tang <[email protected]>
---
.../devicetree/bindings/input/ti,nspire-keypad.txt | 60 ++++
drivers/input/keyboard/Kconfig | 10 +
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/nspire-keypad.c | 315 +++++++++++++++++++++
4 files changed, 386 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/ti,nspire-keypad.txt
create mode 100644 drivers/input/keyboard/nspire-keypad.c
diff --git a/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt b/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt
new file mode 100644
index 0000000..f5b91c6b
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/ti,nspire-keypad.txt
@@ -0,0 +1,60 @@
+TI-NSPIRE Keypad
+
+Required properties:
+- compatible: Compatible property value should be "ti,nspire-keypad".
+
+- reg: Physical base address of the peripheral and length of memory mapped
+ region.
+
+- interrupts: The interrupt number for the peripheral.
+
+- scan-interval: How often to scan in us. Based on a APB speed of 33MHz, the
+ maximum delay time is ...us
+
+- row-delay: How long to wait before scanning each row.
+
+- clocks: The clock this peripheral is attached to.
+
+- keymap: The keymap to use
+ (see Documentation/devicetree/bindings/input/matrix-keymap.txt)
+
+Optional properties:
+- active-low: Specify that the keypad is active low (i.e. logical low signifies
+ a key press).
+
+Example:
+
+input {
+ compatible = "ti,nspire-keypad";
+ reg = <0x900E0000 0x1000>;
+ interrupts = <16>;
+
+ scan-interval = <1000>;
+ row-delay = <200>;
+
+ clocks = <&apb_pclk>;
+
+ keymap = <
+ 0x0000001c 0x0001001c 0x00040039
+ 0x0005002c 0x00060015 0x0007000b
+ 0x0008000f 0x0100002d 0x01010011
+ 0x0102002f 0x01030004 0x01040016
+ 0x01050014 0x0106001f 0x01070002
+ 0x010a006a 0x02000013 0x02010010
+ 0x02020019 0x02030007 0x02040018
+ 0x02050031 0x02060032 0x02070005
+ 0x02080028 0x0209006c 0x03000026
+ 0x03010025 0x03020024 0x0303000a
+ 0x03040017 0x03050023 0x03060022
+ 0x03070008 0x03080035 0x03090069
+ 0x04000021 0x04010012 0x04020020
+ 0x0404002e 0x04050030 0x0406001e
+ 0x0407000d 0x04080037 0x04090067
+ 0x05010038 0x0502000c 0x0503001b
+ 0x05040034 0x0505001a 0x05060006
+ 0x05080027 0x0509000e 0x050a006f
+ 0x0600002b 0x0602004e 0x06030068
+ 0x06040003 0x0605006d 0x06060009
+ 0x06070001 0x0609000f 0x0708002a
+ 0x0709001d 0x070a0033 >;
+};
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 62a2c0e..bdbda87 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -418,6 +418,16 @@ config KEYBOARD_NOMADIK
To compile this driver as a module, choose M here: the
module will be called nmk-ske-keypad.
+config KEYBOARD_NSPIRE
+ tristate "TI-NSPIRE builtin keyboard"
+ depends on ARCH_NSPIRE
+ select INPUT_MATRIXKMAP
+ help
+ Say Y here if you want to use the builtin keypad on the TI-NSPIRE.
+
+ To compile this driver as a module, choose M here: the
+ module will be called nspire-keypad.
+
config KEYBOARD_TEGRA
tristate "NVIDIA Tegra internal matrix keyboard controller support"
depends on ARCH_TEGRA && OF
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 0c43e8c..a699b61 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o
obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o
+obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o
obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o
diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c
new file mode 100644
index 0000000..b922390
--- /dev/null
+++ b/drivers/input/keyboard/nspire-keypad.c
@@ -0,0 +1,315 @@
+/*
+ * linux/drivers/input/keyboard/nspire-keypad.c
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/input/matrix_keypad.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#define KEYPAD_SCAN_MODE 0x00
+#define KEYPAD_CNTL 0x04
+#define KEYPAD_INT 0x08
+#define KEYPAD_INTMSK 0x0C
+
+#define KEYPAD_DATA 0x10
+#define KEYPAD_GPIO 0x30
+
+#define KEYPAD_UNKNOWN_INT 0x40
+#define KEYPAD_UNKNOWN_INT_STS 0x44
+
+#define KEYPAD_BITMASK_COLS 11
+#define KEYPAD_BITMASK_ROWS 8
+
+struct nspire_keypad {
+ spinlock_t lock;
+
+ void __iomem *reg_base;
+ int irq;
+ u32 int_mask;
+
+ struct input_dev *input;
+ struct clk *clk;
+
+ struct matrix_keymap_data *keymap;
+ int row_shift;
+
+ /* Maximum delay estimated assuming 33MHz APB */
+ u32 scan_interval; /* In microseconds (~2000us max) */
+ u32 row_delay; /* In microseconds (~500us max) */
+
+ bool active_low;
+};
+
+static inline void nspire_report_state(struct nspire_keypad *keypad,
+ int row, int col, unsigned int state)
+{
+ int code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
+ unsigned short *keymap = keypad->input->keycode;
+
+ state = keypad->active_low ? !state : !!state;
+ input_report_key(keypad->input, keymap[code], state);
+}
+
+static irqreturn_t nspire_keypad_irq(int irq, void *dev_id)
+{
+ struct nspire_keypad *keypad = dev_id;
+ u32 int_sts;
+ u16 state[8];
+ int row, col;
+
+ int_sts = readl(keypad->reg_base + KEYPAD_INT) & keypad->int_mask;
+
+ if (!int_sts)
+ return IRQ_NONE;
+
+ spin_lock(&keypad->lock);
+
+ memcpy_fromio(state, keypad->reg_base + KEYPAD_DATA, sizeof(state));
+
+ for (row = 0; row < KEYPAD_BITMASK_ROWS; row++) {
+ u16 bits = state[row];
+ for (col = 0; col < KEYPAD_BITMASK_COLS; col++)
+ nspire_report_state(keypad, row, col, bits & (1<<col));
+ }
+ input_sync(keypad->input);
+ writel(0x3, keypad->reg_base + KEYPAD_INT);
+
+ spin_unlock(&keypad->lock);
+
+ return IRQ_HANDLED;
+}
+
+static int nspire_keypad_chip_init(struct nspire_keypad *keypad)
+{
+ unsigned long val = 0, cycles_per_us, delay_cycles, row_delay_cycles;
+
+ cycles_per_us = (clk_get_rate(keypad->clk) / 1000000);
+ if (cycles_per_us == 0)
+ cycles_per_us = 1;
+
+ delay_cycles = cycles_per_us * keypad->scan_interval;
+ WARN_ON(delay_cycles >= (1<<16)); /* Overflow */
+ delay_cycles &= 0xffff;
+
+ row_delay_cycles = cycles_per_us * keypad->row_delay;
+ WARN_ON(row_delay_cycles >= (1<<14)); /* Overflow */
+ row_delay_cycles &= 0x3fff;
+
+
+ val |= (3<<0); /* Set scan mode to 3 (continuous scan) */
+ val |= (row_delay_cycles<<2); /* Delay between scanning each row */
+ val |= (delay_cycles<<16); /* Delay between scans */
+ writel(val, keypad->reg_base + KEYPAD_SCAN_MODE);
+
+ val = (KEYPAD_BITMASK_ROWS & 0xff) | (KEYPAD_BITMASK_COLS & 0xff)<<8;
+ writel(val, keypad->reg_base + KEYPAD_CNTL);
+
+ /* Enable interrupts */
+ keypad->int_mask = (1<<1);
+ writel(keypad->int_mask, keypad->reg_base + 0xc);
+
+ /* Disable GPIO interrupts to prevent hanging on touchpad */
+ /* Possibly used to detect touchpad events */
+ writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT);
+ /* Acknowledge existing interrupts */
+ writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS);
+
+ return 0;
+}
+
+static int nspire_keypad_probe(struct platform_device *pdev)
+{
+ const struct device_node *of_node = pdev->dev.of_node;
+ struct nspire_keypad *keypad;
+ struct input_dev *input;
+ struct resource *res;
+ struct clk *clk;
+ int irq, error;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "failed to get keypad irq\n");
+ return -EINVAL;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "missing platform resources\n");
+ return -EINVAL;
+ }
+
+ clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "unable to get clock\n");
+ return -EINVAL;
+ }
+
+ clk_prepare(clk);
+ error = clk_enable(clk);
+ if (error)
+ goto err_put_clk;
+
+ keypad = kzalloc(sizeof(struct nspire_keypad), GFP_KERNEL);
+ input = input_allocate_device();
+ if (!keypad || !input) {
+ dev_err(&pdev->dev, "failed to allocate keypad memory\n");
+ error = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ error = of_property_read_u32(of_node, "scan-interval",
+ &keypad->scan_interval);
+ if (error) {
+ dev_err(&pdev->dev, "failed to get scan-interval\n");
+ goto err_free_mem;
+ }
+
+ error = of_property_read_u32(of_node, "row-delay",
+ &keypad->row_delay);
+ if (error) {
+ dev_err(&pdev->dev, "failed to get row-delay\n");
+ goto err_free_mem;
+ }
+
+ keypad->active_low = of_property_read_bool(of_node,
+ "active-low");
+
+ keypad->keymap = NULL;
+
+ keypad->row_shift = get_count_order(KEYPAD_BITMASK_COLS);
+ keypad->irq = irq;
+ keypad->clk = clk;
+ keypad->input = input;
+ spin_lock_init(&keypad->lock);
+
+ if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+ dev_err(&pdev->dev, "failed to request I/O memory\n");
+ error = -EBUSY;
+ goto err_free_mem;
+ }
+
+ keypad->reg_base = ioremap(res->start, resource_size(res));
+ if (!keypad->reg_base) {
+ dev_err(&pdev->dev, "failed to remap I/O memory\n");
+ error = -ENXIO;
+ goto err_free_mem_region;
+ }
+
+ input->id.bustype = BUS_HOST;
+ input->name = "nspire-keypad";
+ input->dev.parent = &pdev->dev;
+
+ set_bit(EV_KEY, input->evbit);
+ set_bit(EV_REP, input->evbit);
+
+ error = matrix_keypad_build_keymap(keypad->keymap, "keymap",
+ KEYPAD_BITMASK_ROWS, KEYPAD_BITMASK_COLS, NULL, input);
+ if (error) {
+ dev_err(&pdev->dev, "building keymap failed\n");
+ goto err_iounmap;
+ }
+
+ error = nspire_keypad_chip_init(keypad);
+ if (error) {
+ dev_err(&pdev->dev, "unable to init keypad hardware\n");
+ goto err_iounmap;
+ }
+
+ error = request_irq(keypad->irq, nspire_keypad_irq, 0,
+ "nspire_keypad", keypad);
+ if (error) {
+ dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq);
+ goto err_iounmap;
+ }
+
+ error = input_register_device(input);
+ if (error) {
+ dev_err(&pdev->dev,
+ "unable to register input device: %d\n", error);
+ goto err_free_irq;
+ }
+
+ platform_set_drvdata(pdev, keypad);
+
+ dev_info(&pdev->dev, "TI-NSPIRE keypad at %#08x ("
+ "scan_interval=%uus,row_delay=%uus"
+ "%s)\n", res->start,
+ keypad->row_delay,
+ keypad->scan_interval,
+ keypad->active_low ? ",active_low" : "");
+
+ return 0;
+
+err_free_irq:
+ free_irq(keypad->irq, keypad);
+err_iounmap:
+ iounmap(keypad->reg_base);
+err_free_mem_region:
+ release_mem_region(res->start, resource_size(res));
+err_free_mem:
+ input_free_device(input);
+ kfree(keypad);
+
+ clk_disable(clk);
+err_put_clk:
+ clk_unprepare(clk);
+ clk_put(clk);
+ return error;
+}
+
+static int nspire_keypad_remove(struct platform_device *pdev)
+{
+ struct nspire_keypad *keypad = platform_get_drvdata(pdev);
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ free_irq(keypad->irq, keypad);
+
+ input_unregister_device(keypad->input);
+
+ iounmap(keypad->reg_base);
+ release_mem_region(res->start, resource_size(res));
+ kfree(keypad);
+
+ clk_disable(keypad->clk);
+ clk_unprepare(keypad->clk);
+ clk_put(keypad->clk);
+
+ return 0;
+}
+#ifdef CONFIG_OF
+static const struct of_device_id nspire_keypad_dt_match[] = {
+ { .compatible = "ti,nspire-keypad" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, nspire_keypad_dt_match);
+#endif
+
+static struct platform_driver nspire_keypad_driver = {
+ .driver = {
+ .name = "nspire-keypad",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(nspire_keypad_dt_match),
+ },
+ .remove = nspire_keypad_remove,
+ .probe = nspire_keypad_probe,
+};
+
+module_platform_driver(nspire_keypad_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TI-NSPIRE Keypad Driver");
--
1.8.1.3
Add support for the interrupt controller on TI-Nspires.
Signed-off-by: Daniel Tang <[email protected]>
---
.../interrupt-controller/lsi,zevio-intc.txt | 18 +++
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-zevio.c | 177 +++++++++++++++++++++
3 files changed, 196 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt
create mode 100644 drivers/irqchip/irq-zevio.c
diff --git a/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt
new file mode 100644
index 0000000..aee38e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt
@@ -0,0 +1,18 @@
+TI-NSPIRE interrupt controller
+
+Required properties:
+- compatible: Compatible property value should be "lsi,zevio-intc".
+
+- reg: Physical base address of the controller and length of memory mapped
+ region.
+
+- interrupt-controller : Identifies the node as an interrupt controller
+
+Example:
+
+interrupt-controller {
+ compatible = "lsi,zevio-intc";
+ interrupt-controller;
+ reg = <0xDC000000 0x1000>;
+ #interrupt-cells = <1>;
+};
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index cda4cb5..f313d14 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -15,4 +15,5 @@ obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o
obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
+obj-$(CONFIG_ARCH_NSPIRE) += irq-zevio.o
obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o
diff --git a/drivers/irqchip/irq-zevio.c b/drivers/irqchip/irq-zevio.c
new file mode 100644
index 0000000..3101c2a
--- /dev/null
+++ b/drivers/irqchip/irq-zevio.c
@@ -0,0 +1,177 @@
+/*
+ * linux/drivers/irqchip/irq-nspire-classic.c
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/mach/irq.h>
+#include <asm/exception.h>
+
+#include "irqchip.h"
+
+#define IO_STATUS 0x000
+#define IO_RAW_STATUS 0x004
+#define IO_ENABLE 0x008
+#define IO_DISABLE 0x00C
+#define IO_CURRENT 0x020
+#define IO_RESET 0x028
+#define IO_MAX_PRIOTY 0x02C
+
+#define IO_IRQ_BASE 0x000
+#define IO_FIQ_BASE 0x100
+
+#define IO_INVERT_SEL 0x200
+#define IO_STICKY_SEL 0x204
+#define IO_PRIORITY_SEL 0x300
+
+#define MAX_INTRS 32
+#define FIQ_START MAX_INTRS
+
+
+static void __iomem *irq_io_base;
+static struct irq_domain *nspire_irq_domain;
+
+static void nspire_irq_ack(struct irq_data *irqd)
+{
+ void __iomem *base = irq_io_base;
+
+ if (irqd->hwirq < FIQ_START)
+ base += IO_IRQ_BASE;
+ else
+ base += IO_FIQ_BASE;
+
+ readl(base + IO_RESET);
+}
+
+static void nspire_irq_unmask(struct irq_data *irqd)
+{
+ void __iomem *base = irq_io_base;
+ int irqnr = irqd->hwirq;
+
+ if (irqnr < FIQ_START) {
+ base += IO_IRQ_BASE;
+ } else {
+ irqnr -= MAX_INTRS;
+ base += IO_FIQ_BASE;
+ }
+
+ writel((1<<irqnr), base + IO_ENABLE);
+}
+
+static void nspire_irq_mask(struct irq_data *irqd)
+{
+ void __iomem *base = irq_io_base;
+ int irqnr = irqd->hwirq;
+
+ if (irqnr < FIQ_START) {
+ base += IO_IRQ_BASE;
+ } else {
+ irqnr -= FIQ_START;
+ base += IO_FIQ_BASE;
+ }
+
+ writel((1<<irqnr), base + IO_DISABLE);
+}
+
+static struct irq_chip nspire_irq_chip = {
+ .name = "nspire_irq",
+ .irq_ack = nspire_irq_ack,
+ .irq_mask = nspire_irq_mask,
+ .irq_unmask = nspire_irq_unmask,
+};
+
+
+static int nspire_irq_map(struct irq_domain *dom, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(virq, &nspire_irq_chip, handle_level_irq);
+ set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+
+ return 0;
+}
+
+static struct irq_domain_ops nspire_irq_ops = {
+ .map = nspire_irq_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+static void init_base(void __iomem *base)
+{
+ /* Disable all interrupts */
+ writel(~0, base + IO_DISABLE);
+
+ /* Accept interrupts of all priorities */
+ writel(0xF, base + IO_MAX_PRIOTY);
+
+ /* Reset existing interrupts */
+ readl(base + IO_RESET);
+}
+
+static int process_base(void __iomem *base, struct pt_regs *regs)
+{
+ int irqnr;
+
+
+ if (!readl(base + IO_STATUS))
+ return 0;
+
+ irqnr = readl(base + IO_CURRENT);
+ irqnr = irq_find_mapping(nspire_irq_domain, irqnr);
+ handle_IRQ(irqnr, regs);
+
+ return 1;
+}
+
+asmlinkage void __exception_irq_entry nspire_handle_irq(struct pt_regs *regs)
+{
+ while (process_base(irq_io_base + IO_FIQ_BASE, regs))
+ ;
+ while (process_base(irq_io_base + IO_IRQ_BASE, regs))
+ ;
+}
+
+static int __init nspire_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ if (WARN_ON(irq_io_base))
+ return -EBUSY;
+
+ irq_io_base = of_iomap(node, 0);
+ BUG_ON(!irq_io_base);
+
+ /* Do not invert interrupt status bits */
+ writel(~0, irq_io_base + IO_INVERT_SEL);
+
+ /* Disable sticky interrupts */
+ writel(0, irq_io_base + IO_STICKY_SEL);
+
+ /* We don't use IRQ priorities. Set each IRQ to highest priority. */
+ memset_io(irq_io_base + IO_PRIORITY_SEL, 0, MAX_INTRS * sizeof(u32));
+
+ /* Init IRQ and FIQ */
+ init_base(irq_io_base + IO_IRQ_BASE);
+ init_base(irq_io_base + IO_FIQ_BASE);
+
+ nspire_irq_domain = irq_domain_add_linear(node, MAX_INTRS,
+ &nspire_irq_ops, NULL);
+
+ BUG_ON(!nspire_irq_domain);
+
+ set_handle_irq(nspire_handle_irq);
+
+ pr_info("TI-NSPIRE classic IRQ controller\n");
+ return 0;
+}
+
+IRQCHIP_DECLARE(nspire_classic_irq, "lsi,zevio-intc", nspire_of_init);
--
1.8.1.3
Add initial platform support for the TI-Nspire series.
Signed-off-by: Daniel Tang <[email protected]>
---
arch/arm/Kconfig | 2 +
arch/arm/Kconfig.debug | 16 +++++
arch/arm/Makefile | 1 +
arch/arm/include/debug/nspire.S | 28 +++++++++
arch/arm/mach-nspire/Kconfig | 15 +++++
arch/arm/mach-nspire/Makefile | 2 +
arch/arm/mach-nspire/Makefile.boot | 0
arch/arm/mach-nspire/clcd.c | 119 +++++++++++++++++++++++++++++++++++++
arch/arm/mach-nspire/clcd.h | 14 +++++
arch/arm/mach-nspire/mmio.h | 23 +++++++
arch/arm/mach-nspire/nspire.c | 117 ++++++++++++++++++++++++++++++++++++
11 files changed, 337 insertions(+)
create mode 100644 arch/arm/include/debug/nspire.S
create mode 100644 arch/arm/mach-nspire/Kconfig
create mode 100644 arch/arm/mach-nspire/Makefile
create mode 100644 arch/arm/mach-nspire/Makefile.boot
create mode 100644 arch/arm/mach-nspire/clcd.c
create mode 100644 arch/arm/mach-nspire/clcd.h
create mode 100644 arch/arm/mach-nspire/mmio.h
create mode 100644 arch/arm/mach-nspire/nspire.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 49d993c..86a3ed9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -964,6 +964,8 @@ source "arch/arm/mach-netx/Kconfig"
source "arch/arm/mach-nomadik/Kconfig"
+source "arch/arm/mach-nspire/Kconfig"
+
source "arch/arm/plat-omap/Kconfig"
source "arch/arm/mach-omap1/Kconfig"
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 1d41908..fe07941 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -309,6 +309,20 @@ choice
Say Y here if you want kernel low-level debugging support
on MVEBU based platforms.
+ config DEBUG_NSPIRE_CLASSIC_UART
+ bool "Kernel low-level debugging via TI-NSPIRE 8250 UART"
+ depends on ARCH_NSPIRE
+ help
+ Say Y here if you want kernel low-level debugging support
+ on TI-NSPIRE classic models.
+
+ config DEBUG_NSPIRE_CX_UART
+ bool "Kernel low-level debugging via TI-NSPIRE PL011 UART"
+ depends on ARCH_NSPIRE
+ help
+ Say Y here if you want kernel low-level debugging support
+ on TI-NSPIRE CX models.
+
config DEBUG_NOMADIK_UART
bool "Kernel low-level debugging messages via NOMADIK UART"
depends on ARCH_NOMADIK
@@ -633,6 +647,8 @@ config DEBUG_LL_INCLUDE
DEBUG_IMX53_UART ||\
DEBUG_IMX6Q_UART
default "debug/mvebu.S" if DEBUG_MVEBU_UART
+ default "debug/nspire.S" if DEBUG_NSPIRE_CX_UART || \
+ DEBUG_NSPIRE_CLASSIC_UART
default "debug/mxs.S" if DEBUG_IMX23_UART || DEBUG_IMX28_UART
default "debug/nomadik.S" if DEBUG_NOMADIK_UART
default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1ba358b..b4615aa 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -164,6 +164,7 @@ machine-$(CONFIG_ARCH_MXS) += mxs
machine-$(CONFIG_ARCH_MVEBU) += mvebu
machine-$(CONFIG_ARCH_NETX) += netx
machine-$(CONFIG_ARCH_NOMADIK) += nomadik
+machine-$(CONFIG_ARCH_NSPIRE) += nspire
machine-$(CONFIG_ARCH_OMAP1) += omap1
machine-$(CONFIG_ARCH_OMAP2PLUS) += omap2
machine-$(CONFIG_ARCH_ORION5X) += orion5x
diff --git a/arch/arm/include/debug/nspire.S b/arch/arm/include/debug/nspire.S
new file mode 100644
index 0000000..886fd27
--- /dev/null
+++ b/arch/arm/include/debug/nspire.S
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/arm/include/debug/nspire.S
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define NSPIRE_EARLY_UART_PHYS_BASE 0x90020000
+#define NSPIRE_EARLY_UART_VIRT_BASE 0xfee20000
+
+.macro addruart, rp, rv, tmp
+ ldr \rp, =(NSPIRE_EARLY_UART_PHYS_BASE) @ physical base address
+ ldr \rv, =(NSPIRE_EARLY_UART_VIRT_BASE) @ virtual base address
+.endm
+
+
+#ifdef CONFIG_DEBUG_NSPIRE_CX_UART
+#include <asm/hardware/debug-pl01x.S>
+#endif
+
+#ifdef CONFIG_DEBUG_NSPIRE_CLASSIC_UART
+#define UART_SHIFT 2
+#include <asm/hardware/debug-8250.S>
+#endif
diff --git a/arch/arm/mach-nspire/Kconfig b/arch/arm/mach-nspire/Kconfig
new file mode 100644
index 0000000..a295b18
--- /dev/null
+++ b/arch/arm/mach-nspire/Kconfig
@@ -0,0 +1,15 @@
+config ARCH_NSPIRE
+ bool "TI-NSPIRE based"
+ depends on ARCH_MULTI_V4_V5
+ depends on MMU
+ select CPU_ARM926T
+ select COMMON_CLK
+ select GENERIC_CLOCKEVENTS
+ select SPARSE_IRQ
+ select ARM_AMBA
+ select ARM_VIC
+ select ARM_TIMER_SP804
+ select USE_OF
+ select CLKSRC_OF
+ help
+ This enables support for systems using the TI-NSPIRE CPU
diff --git a/arch/arm/mach-nspire/Makefile b/arch/arm/mach-nspire/Makefile
new file mode 100644
index 0000000..1bec256
--- /dev/null
+++ b/arch/arm/mach-nspire/Makefile
@@ -0,0 +1,2 @@
+obj-y += nspire.o
+obj-y += clcd.o
diff --git a/arch/arm/mach-nspire/Makefile.boot b/arch/arm/mach-nspire/Makefile.boot
new file mode 100644
index 0000000..e69de29
diff --git a/arch/arm/mach-nspire/clcd.c b/arch/arm/mach-nspire/clcd.c
new file mode 100644
index 0000000..abea126
--- /dev/null
+++ b/arch/arm/mach-nspire/clcd.c
@@ -0,0 +1,119 @@
+/*
+ * linux/arch/arm/mach-nspire/clcd.c
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/dma-mapping.h>
+
+static struct clcd_panel nspire_cx_lcd_panel = {
+ .mode = {
+ .name = "Color LCD",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .pixclock = 1,
+ .hsync_len = 6,
+ .vsync_len = 1,
+ .right_margin = 50,
+ .left_margin = 38,
+ .lower_margin = 3,
+ .upper_margin = 17,
+ },
+ .width = 65, /* ~6.50 cm */
+ .height = 49, /* ~4.87 cm */
+ .tim2 = TIM2_IPC,
+ .cntl = CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+ .bpp = 16,
+ .caps = CLCD_CAP_565,
+};
+
+static struct clcd_panel nspire_classic_lcd_panel = {
+ .mode = {
+ .name = "Grayscale LCD",
+ .refresh = 60,
+ .xres = 320,
+ .yres = 240,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ .pixclock = 1,
+ .hsync_len = 6,
+ .vsync_len = 1,
+ .right_margin = 6,
+ .left_margin = 6,
+ },
+ .width = 71, /* 7.11cm */
+ .height = 53, /* 5.33cm */
+ .tim2 = 0x80007d0,
+ .cntl = CNTL_LCDMONO8,
+ .bpp = 8,
+ .grayscale = 1,
+ .caps = CLCD_CAP_5551,
+};
+
+int nspire_clcd_setup(struct clcd_fb *fb)
+{
+ struct clcd_panel *panel;
+ size_t panel_size;
+ const char *type;
+ dma_addr_t dma;
+ int err;
+
+ BUG_ON(!fb->dev->dev.of_node);
+
+ err = of_property_read_string(fb->dev->dev.of_node, "lcd-type", &type);
+ if (err) {
+ pr_err("CLCD: Could not find lcd-type property\n");
+ return err;
+ }
+
+ if (!strcmp(type, "cx")) {
+ panel = &nspire_cx_lcd_panel;
+ } else if (!strcmp(type, "classic")) {
+ panel = &nspire_classic_lcd_panel;
+ } else {
+ pr_err("CLCD: Unknown lcd-type %s\n", type);
+ return -EINVAL;
+ }
+
+ panel_size = ((panel->mode.xres * panel->mode.yres) * panel->bpp) / 8;
+ panel_size = ALIGN(panel_size, PAGE_SIZE);
+
+ fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
+ panel_size, &dma, GFP_KERNEL);
+
+ if (!fb->fb.screen_base) {
+ pr_err("CLCD: unable to map framebuffer\n");
+ return -ENOMEM;
+ }
+
+ fb->fb.fix.smem_start = dma;
+ fb->fb.fix.smem_len = panel_size;
+ fb->panel = panel;
+
+ return 0;
+}
+
+int nspire_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+ return dma_mmap_writecombine(&fb->dev->dev, vma,
+ fb->fb.screen_base, fb->fb.fix.smem_start,
+ fb->fb.fix.smem_len);
+}
+
+void nspire_clcd_remove(struct clcd_fb *fb)
+{
+ dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+ fb->fb.screen_base, fb->fb.fix.smem_start);
+}
diff --git a/arch/arm/mach-nspire/clcd.h b/arch/arm/mach-nspire/clcd.h
new file mode 100644
index 0000000..8c33d2c
--- /dev/null
+++ b/arch/arm/mach-nspire/clcd.h
@@ -0,0 +1,14 @@
+/*
+ * linux/arch/arm/mach-nspire/clcd.h
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+int nspire_clcd_setup(struct clcd_fb *fb);
+int nspire_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma);
+void nspire_clcd_remove(struct clcd_fb *fb);
diff --git a/arch/arm/mach-nspire/mmio.h b/arch/arm/mach-nspire/mmio.h
new file mode 100644
index 0000000..4de63fc
--- /dev/null
+++ b/arch/arm/mach-nspire/mmio.h
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-nspire/mmio.h
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define NSPIRE_EARLY_UART_PHYS_BASE 0x90020000
+#define NSPIRE_EARLY_UART_VIRT_BASE 0xFEE20000
+
+#define NSPIRE_MISC_PHYS_BASE 0x900A0000
+#define NSPIRE_MISC_HWRESET 0x08
+
+#define NSPIRE_PWR_PHYS_BASE 0x900B0000
+#define NSPIRE_PWR_VIRT_BASE 0xFEEB0000
+#define NSPIRE_PWR_BUS_DISABLE1 0x18
+#define NSPIRE_PWR_BUS_DISABLE2 0x20
+
+#define NSPIRE_LCD_PHYS_BASE 0xC0000000
diff --git a/arch/arm/mach-nspire/nspire.c b/arch/arm/mach-nspire/nspire.c
new file mode 100644
index 0000000..d26c46d
--- /dev/null
+++ b/arch/arm/mach-nspire/nspire.c
@@ -0,0 +1,117 @@
+/*
+ * linux/arch/arm/mach-nspire/nspire.c
+ *
+ * Copyright (C) 2013 Daniel Tang <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/init.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-vic.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/clocksource.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#include <asm/hardware/timer-sp.h>
+
+#include "mmio.h"
+#include "clcd.h"
+
+static const char *nspire_dt_match[] __initconst = {
+ "ti,nspire",
+ "ti,nspire-cx",
+ "ti,nspire-tp",
+ "ti,nspire-clp",
+ NULL,
+};
+
+static struct map_desc nspire_io_desc[] __initdata = {
+ {
+ .virtual = NSPIRE_EARLY_UART_VIRT_BASE,
+ .pfn = __phys_to_pfn(NSPIRE_EARLY_UART_PHYS_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ },
+ {
+ .virtual = NSPIRE_PWR_VIRT_BASE,
+ .pfn = __phys_to_pfn(NSPIRE_PWR_PHYS_BASE),
+ .length = SZ_4K,
+ .type = MT_DEVICE
+ }
+};
+
+static void __init nspire_map_io(void)
+{
+ iotable_init(nspire_io_desc, ARRAY_SIZE(nspire_io_desc));
+}
+
+static struct clcd_board nspire_clcd_data = {
+ .name = "LCD",
+ .caps = CLCD_CAP_5551 | CLCD_CAP_565,
+ .check = clcdfb_check,
+ .decode = clcdfb_decode,
+ .setup = nspire_clcd_setup,
+ .mmap = nspire_clcd_mmap,
+ .remove = nspire_clcd_remove,
+};
+
+
+static struct of_dev_auxdata nspire_auxdata[] __initdata = {
+ OF_DEV_AUXDATA("arm,pl111", NSPIRE_LCD_PHYS_BASE,
+ NULL, &nspire_clcd_data),
+ { }
+};
+
+static void __init nspire_early_init(void)
+{
+ void __iomem *pwr = IOMEM(NSPIRE_PWR_VIRT_BASE);
+
+ /* Re-enable bus access to all peripherals */
+ writel(0, pwr + NSPIRE_PWR_BUS_DISABLE1);
+ writel(0, pwr + NSPIRE_PWR_BUS_DISABLE2);
+
+ pr_info("Re-enabled bus access to all peripherals\n");
+}
+
+static void __init nspire_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table,
+ nspire_auxdata, NULL);
+}
+
+static void __init nspire_init_time(void)
+{
+ of_clk_init(NULL);
+ clocksource_of_init();
+}
+
+static void nspire_restart(char mode, const char *cmd)
+{
+ void __iomem *base = ioremap(NSPIRE_MISC_PHYS_BASE, SZ_4K);
+ if (!base)
+ return;
+
+ writel(2, base + NSPIRE_MISC_HWRESET);
+}
+
+DT_MACHINE_START(NSPIRE, "TI-NSPIRE")
+ .map_io = nspire_map_io,
+ .init_irq = irqchip_init,
+ .init_time = nspire_init_time,
+ .init_machine = nspire_init,
+ .init_early = nspire_early_init,
+ .dt_compat = nspire_dt_match,
+ .restart = nspire_restart,
+MACHINE_END
--
1.8.1.3
On Saturday 25 May 2013, Daniel Tang wrote:
> +static struct map_desc nspire_io_desc[] __initdata = {
> + {
> + .virtual = NSPIRE_EARLY_UART_VIRT_BASE,
> + .pfn = __phys_to_pfn(NSPIRE_EARLY_UART_PHYS_BASE),
> + .length = SZ_4K,
> + .type = MT_DEVICE
> + },
You can remove this now and call debug_ll_io_init() instead, so you can
remove the duplicate definitions of the base addresses.
> + {
> + .virtual = NSPIRE_PWR_VIRT_BASE,
> + .pfn = __phys_to_pfn(NSPIRE_PWR_PHYS_BASE),
> + .length = SZ_4K,
> + .type = MT_DEVICE
> + }
> +};
And I think this one can be replaced with a call to of_iomap:
> +static void __init nspire_early_init(void)
> +{
> + void __iomem *pwr = IOMEM(NSPIRE_PWR_VIRT_BASE);
> +
> + /* Re-enable bus access to all peripherals */
> + writel(0, pwr + NSPIRE_PWR_BUS_DISABLE1);
> + writel(0, pwr + NSPIRE_PWR_BUS_DISABLE2);
> +
> + pr_info("Re-enabled bus access to all peripherals\n");
> +}
Since it seems to be used only in this one function.
> +DT_MACHINE_START(NSPIRE, "TI-NSPIRE")
> + .map_io = nspire_map_io,
> + .init_irq = irqchip_init,
> + .init_time = nspire_init_time,
> + .init_machine = nspire_init,
> + .init_early = nspire_early_init,
> + .dt_compat = nspire_dt_match,
> + .restart = nspire_restart,
> +MACHINE_END
The reference to irqchip_init is now the default, so you can drop that too.
nspire_init_time is still needed right now, but I'd like to initialize the
clocks automatically soon, so that will go away in the future.
Please reorder the other callbacks in call order, same as the structure
definition.
Arnd
On Saturday 25 May 2013, Daniel Tang wrote:
> Changes between v3 and v4:
> * Remove redundant clock-names in device tree
> * Re-enable bus access to some peripherals on bootup
> * Clean up nspire-classic-timer code.
> - Implement a nspire_timer_set_mode function
> - Removed messy IO_MATCHx and CNTL_MATCHx macros
> - Timer starts disabled to begin with
> - Interrupt handling code return IRQ_NONE for spurious interrupts
> - Delete unnessecary shift
> * Change clk-nspire to use compatible property to determine IO type
> * Change device tree bindings to have appropriate vendor prefixes
> * Added device tree binding documentation
> * Fix incorrect register addresses for clocks
> * Use more specific .caps for CLCD
Looks really good now. I have a few more comments for the first patch,
mostly for stuff that can be simplified based on stuff we merged in 3.10.
The one remaining bit that sticks out is the clcd platform data. As I
said before, I won't require you to convert that to DT in order to
get your code merged, but I'd also really like to see that happen,
as we will also need that to get rid of auxdata on the ARM reference
platforms (integrator, versatile, realview, vexpress).
Are you motivated to look into those after the base patch gets
merged into arm-soc?
One comment on the merge path: While we can put any of the patches
into the arm-soc tree, my preference is definitely for the clk,
clksource, irqchip and input drivers to go through the respective
maintainer trees. There are no dependencies to worry about, since
each patch can compile standalone, and we just need to make sure
they all get into 3.11 for your platform to work.
Arnd
On 27/05/2013, at 7:23 AM, Arnd Bergmann <[email protected]> wrote:
> On Saturday 25 May 2013, Daniel Tang wrote:
>> Changes between v3 and v4:
>> * Remove redundant clock-names in device tree
>> * Re-enable bus access to some peripherals on bootup
>> * Clean up nspire-classic-timer code.
>> - Implement a nspire_timer_set_mode function
>> - Removed messy IO_MATCHx and CNTL_MATCHx macros
>> - Timer starts disabled to begin with
>> - Interrupt handling code return IRQ_NONE for spurious interrupts
>> - Delete unnessecary shift
>> * Change clk-nspire to use compatible property to determine IO type
>> * Change device tree bindings to have appropriate vendor prefixes
>> * Added device tree binding documentation
>> * Fix incorrect register addresses for clocks
>> * Use more specific .caps for CLCD
>
> Looks really good now. I have a few more comments for the first patch,
> mostly for stuff that can be simplified based on stuff we merged in 3.10.
>
> The one remaining bit that sticks out is the clcd platform data. As I
> said before, I won't require you to convert that to DT in order to
> get your code merged, but I'd also really like to see that happen,
> as we will also need that to get rid of auxdata on the ARM reference
> platforms (integrator, versatile, realview, vexpress).
How would you like me to convert the platform data to DT? AFAIK, the clcd driver isn't aware of DT so the only way is to use the AUXDATA right now.
>
> Are you motivated to look into those after the base patch gets
> merged into arm-soc?
Of course.
>
> One comment on the merge path: While we can put any of the patches
> into the arm-soc tree, my preference is definitely for the clk,
> clksource, irqchip and input drivers to go through the respective
> maintainer trees. There are no dependencies to worry about, since
> each patch can compile standalone, and we just need to make sure
> they all get into 3.11 for your platform to work.
Yeah that's totally fine.
>
> Arnd
Cheers,
Daniel Tang-
On 27/05/2013, at 6:46 AM, Arnd Bergmann <[email protected]> wrote:
>
>
>> + {
>> + .virtual = NSPIRE_PWR_VIRT_BASE,
>> + .pfn = __phys_to_pfn(NSPIRE_PWR_PHYS_BASE),
>> + .length = SZ_4K,
>> + .type = MT_DEVICE
>> + }
>> +};
>
> And I think this one can be replaced with a call to of_iomap:
Does of_iomap work that early in the boot process?
Cheers,
Daniel Tang
On Monday 27 May 2013, Daniel Tang wrote:
>
> On 27/05/2013, at 6:46 AM, Arnd Bergmann <[email protected]> wrote:
> >
> >
> >> + {
> >> + .virtual = NSPIRE_PWR_VIRT_BASE,
> >> + .pfn = __phys_to_pfn(NSPIRE_PWR_PHYS_BASE),
> >> + .length = SZ_4K,
> >> + .type = MT_DEVICE
> >> + }
> >> +};
> >
> > And I think this one can be replaced with a call to of_iomap:
>
> Does of_iomap work that early in the boot process?
Not from map_io, but soon after. What is the fist place you
really need it?
Arnd
On Monday 27 May 2013, Daniel Tang wrote:
> > The one remaining bit that sticks out is the clcd platform data. As I
> > said before, I won't require you to convert that to DT in order to
> > get your code merged, but I'd also really like to see that happen,
> > as we will also need that to get rid of auxdata on the ARM reference
> > platforms (integrator, versatile, realview, vexpress).
>
> How would you like me to convert the platform data to DT? AFAIK, the clcd
> driver isn't aware of DT so the only way is to use the AUXDATA right now.
Linus Walleij mentioned on IRC that Pawel Moll already posted a series
that adds DT support for clcd:
http://lists.freedesktop.org/archives/dri-devel/2013-April/037519.html
The series does a few more things, but you can probbly split out the
parts you need and base on that.
Arnd
On Monday 27 May 2013, Daniel Tang wrote:
> > On Saturday 25 May 2013, Daniel Tang wrote:
> > The one remaining bit that sticks out is the clcd platform data. As I
> > said before, I won't require you to convert that to DT in order to
> > get your code merged, but I'd also really like to see that happen,
> > as we will also need that to get rid of auxdata on the ARM reference
> > platforms (integrator, versatile, realview, vexpress).
>
> How would you like me to convert the platform data to DT? AFAIK, the
> clcd driver isn't aware of DT so the only way is to use the AUXDATA right now.
There are two basica approaches we could take:
a) add DT support to the clcd driver, using the of_get_videomode()
helper and any other properties that need to be added.
b) add a new KMS driver for this hardware that can be used as an
alternative to the existing one and that works with DT.
Arnd
On Sat, May 25, 2013 at 1:08 PM, Daniel Tang <[email protected]> wrote:
> Add clocksource and clockevent driver for the TI-Nspire.
>
> Signed-off-by: Daniel Tang <[email protected]>
This is *much* improved :-D
But:
> +++ b/drivers/clocksource/zevio-timer.c
> +static void zevio_timer_set_mode(enum clock_event_mode mode,
> + struct clock_event_device *dev)
> +{
> + unsigned long flags;
> + struct zevio_timer *timer = container_of(dev,
> + struct zevio_timer,
> + clkevt);
> +
> + local_irq_save(flags);
> +
> + switch (mode) {
> + case CLOCK_EVT_MODE_PERIODIC:
> + /* Unsupported */
> + break;
> + case CLOCK_EVT_MODE_RESUME:
> + case CLOCK_EVT_MODE_ONESHOT:
> + /* Enable timer interrupts */
> + writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK);
> + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
> + dev->mode = mode;
> + break;
> + case CLOCK_EVT_MODE_SHUTDOWN:
> + case CLOCK_EVT_MODE_UNUSED:
> + /* Disable timer interrupts */
> + writel(0, timer->interrupt_regs + IO_INTR_MSK);
> + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
> + /* Stop timer */
> + writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);
> + dev->mode = mode;
> + break;
> + }
Surely both the compiler and checkpatch is complaining that this
switch does not contain a default: clause?
If you fix this you can add my:
Reviewed-by: Linus Walleij <[email protected]>
Yours,
Linus Walleij
On 27/05/2013, at 8:53 PM, Linus Walleij <[email protected]> wrote:
> On Sat, May 25, 2013 at 1:08 PM, Daniel Tang <[email protected]> wrote:
>
>> Add clocksource and clockevent driver for the TI-Nspire.
>>
>> Signed-off-by: Daniel Tang <[email protected]>
>
> This is *much* improved :-D
Awesome!
>> + /* Disable timer interrupts */
>> + writel(0, timer->interrupt_regs + IO_INTR_MSK);
>> + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
>> + /* Stop timer */
>> + writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);
>> + dev->mode = mode;
>> + break;
>> + }
>
> Surely both the compiler and checkpatch is complaining that this
> switch does not contain a default: clause?
Neither in fact. checkpatch.pl gives me a all-clear.
But, I'll clean it up anyway - seems cleaner that way XD.
>
> If you fix this you can add my:
> Reviewed-by: Linus Walleij <[email protected]>
>
> Yours,
> Linus Walleij
Cheers,
Daniel Tang-
On Mon, 27 May 2013, Linus Walleij wrote:
> > +static void zevio_timer_set_mode(enum clock_event_mode mode,
> > + struct clock_event_device *dev)
> > +{
> > + unsigned long flags;
> > + struct zevio_timer *timer = container_of(dev,
> > + struct zevio_timer,
> > + clkevt);
> > +
> > + local_irq_save(flags);
> > +
> > + switch (mode) {
> > + case CLOCK_EVT_MODE_PERIODIC:
> > + /* Unsupported */
> > + break;
> > + case CLOCK_EVT_MODE_RESUME:
> > + case CLOCK_EVT_MODE_ONESHOT:
> > + /* Enable timer interrupts */
> > + writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK);
> > + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
> > + dev->mode = mode;
> > + break;
> > + case CLOCK_EVT_MODE_SHUTDOWN:
> > + case CLOCK_EVT_MODE_UNUSED:
> > + /* Disable timer interrupts */
> > + writel(0, timer->interrupt_regs + IO_INTR_MSK);
> > + writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);
> > + /* Stop timer */
> > + writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);
> > + dev->mode = mode;
> > + break;
> > + }
>
> Surely both the compiler and checkpatch is complaining that this
> switch does not contain a default: clause?
Well, if you have a switch with an enum, the compiler complains if you
do not have a case for each enum value and the above has all enum
values covered AFAICT. :)
Thanks,
tglx
On Mon, 2013-05-27 at 11:31 +0100, Arnd Bergmann wrote:
> On Monday 27 May 2013, Daniel Tang wrote:
> > > The one remaining bit that sticks out is the clcd platform data. As I
> > > said before, I won't require you to convert that to DT in order to
> > > get your code merged, but I'd also really like to see that happen,
> > > as we will also need that to get rid of auxdata on the ARM reference
> > > platforms (integrator, versatile, realview, vexpress).
> >
> > How would you like me to convert the platform data to DT? AFAIK, the clcd
> > driver isn't aware of DT so the only way is to use the AUXDATA right now.
>
> Linus Walleij mentioned on IRC that Pawel Moll already posted a series
> that adds DT support for clcd:
>
> http://lists.freedesktop.org/archives/dri-devel/2013-April/037519.html
>
> The series does a few more things, but you can probbly split out the
> parts you need and base on that.
The main "issue" with the series is its dependency on Laurent Pinchart's
Common Display Framework (or rather on the progress of its upstreaming).
I'm planning to discuss this in details in during the Linaro Connect in
Dublin, but generally, if it's not getting merged in the next window,
I'll spin the series to use the standard video modes bindings instead of
CDF. This will make me hurt on Versatile Express, but should work for
others.
Paweł
On Mon, 2013-05-27 at 11:32 +0100, Arnd Bergmann wrote:
> b) add a new KMS driver for this hardware that can be used as an
> alternative to the existing one and that works with DT.
There are people working on this, just trying to jump through some legal
hoops to post a RFC. Once this is done we'll be in an interesting
position of two amba_bus drivers "competing" for the same amba_bus
device, which I'm not sure how to deal with right now...
Paweł
On Tue, May 28, 2013 at 12:54 PM, Pawel Moll <[email protected]> wrote:
> On Mon, 2013-05-27 at 11:32 +0100, Arnd Bergmann wrote:
>> b) add a new KMS driver for this hardware that can be used as an
>> alternative to the existing one and that works with DT.
>
> There are people working on this, just trying to jump through some legal
> hoops to post a RFC. Once this is done we'll be in an interesting
> position of two amba_bus drivers "competing" for the same amba_bus
> device, which I'm not sure how to deal with right now...
Make them mutually exclusive in Kconfig?
Yours,
Linus Walleij
On Tue, 2013-05-28 at 15:16 +0100, Linus Walleij wrote:
> On Tue, May 28, 2013 at 12:54 PM, Pawel Moll <[email protected]> wrote:
> > On Mon, 2013-05-27 at 11:32 +0100, Arnd Bergmann wrote:
> >> b) add a new KMS driver for this hardware that can be used as an
> >> alternative to the existing one and that works with DT.
> >
> > There are people working on this, just trying to jump through some legal
> > hoops to post a RFC. Once this is done we'll be in an interesting
> > position of two amba_bus drivers "competing" for the same amba_bus
> > device, which I'm not sure how to deal with right now...
>
> Make them mutually exclusive in Kconfig?
Certainly an option.
I wouldn't mind having both compiled as modules and loading one or the
other, but it wouldn't fly with "=y"...
Paweł
On Tuesday 28 May 2013 15:21:04 Pawel Moll wrote:
> On Tue, 2013-05-28 at 15:16 +0100, Linus Walleij wrote:
> > On Tue, May 28, 2013 at 12:54 PM, Pawel Moll <[email protected]> wrote:
> > > On Mon, 2013-05-27 at 11:32 +0100, Arnd Bergmann wrote:
> > >> b) add a new KMS driver for this hardware that can be used as an
> > >> alternative to the existing one and that works with DT.
> > >
> > > There are people working on this, just trying to jump through some legal
> > > hoops to post a RFC. Once this is done we'll be in an interesting
> > > position of two amba_bus drivers "competing" for the same amba_bus
> > > device, which I'm not sure how to deal with right now...
> >
> > Make them mutually exclusive in Kconfig?
>
> Certainly an option.
>
> I wouldn't mind having both compiled as modules and loading one or the
> other, but it wouldn't fly with "=y"...
It's a bit ugly but I think you can express that in Kconfig like this:
config FB_ARMCLCD
tristate "ARM PrimeCell PL110 support"
depends on FB && ARM && ARM_AMBA
depends on KMS_ARMCLCD != 'y'
depends on 'm' if KMS_ARMCLCD
Arnd
On Tue, May 28, 2013 at 5:52 PM, Arnd Bergmann <[email protected]> wrote:
> depends on KMS_ARMCLCD != 'y'
> depends on 'm' if KMS_ARMCLCD
Those two above could be one actually.
Just my 2 cents.
--
With Best Regards,
Andy Shevchenko
On 28/05/2013, at 1:15 AM, Arnd Bergmann <[email protected]> wrote:
> On Monday 27 May 2013, Daniel Tang wrote:
>> Before any peripheral is accessed. I.e. before the clocksource and irqchip
>> drivers.
>
> The irqchip comes first, and by that time, you can actually call
> of_iomap().
>
>> The write to the port is supposed to ensure all mmio peripherals can be
>> accessed. Without it, access to certain peripherals will result in
>> undefined reads or ignored writes.
>>
>> On second thoughts, would this actually be the job of the boot loader?
>
> Doing it in the boot loader would certainly simplify things. I wonder
> about the dynamic aspects of power management though: It might be
> better to expose the individual bits of this register through a proper
> driver. The boot loader can start out enabling everything, but then
> you turn off everything that is not needed when that driver gets
> loaded.
That's the idea for the long term.
For now though, I'll probably just let the bootloader enable everything and work on a proper driver for power management later.
>
> I'm still not sure what the register actually does: Does it
> control reset lines, clock signals, voltage regulators or something
> else? These things all have their own subsystems, and then there
> is also the power domain framework.
To be perfectly honest, I'm not too sure. The documentation for the TI-Nspire is all gathered from reverse engineering and all it says is that register "disables bus access to peripherals".
>
> Arnd
Cheers,
Daniel Tang-
On 27/05/2013, at 8:31 PM, Arnd Bergmann <[email protected]> wrote:
> On Monday 27 May 2013, Daniel Tang wrote:
>>> The one remaining bit that sticks out is the clcd platform data. As I
>>> said before, I won't require you to convert that to DT in order to
>>> get your code merged, but I'd also really like to see that happen,
>>> as we will also need that to get rid of auxdata on the ARM reference
>>> platforms (integrator, versatile, realview, vexpress).
>>
>> How would you like me to convert the platform data to DT? AFAIK, the clcd
>> driver isn't aware of DT so the only way is to use the AUXDATA right now.
>
> Linus Walleij mentioned on IRC that Pawel Moll already posted a series
> that adds DT support for clcd:
>
> http://lists.freedesktop.org/archives/dri-devel/2013-April/037519.html
>
> The series does a few more things, but you can probbly split out the
> parts you need and base on that.
Would it be fine if I waited until CLCD DT patch gets into mainline instead?
>
> Arnd
Cheers,
Daniel Tang
On Wednesday 29 May 2013 15:14:41 Daniel Tang wrote:
>
> That's the idea for the long term.
>
> For now though, I'll probably just let the bootloader enable
> everything and work on a proper driver for power management later.
Ok, sounds good.
Arnd
On Wednesday 29 May 2013, Daniel Tang wrote:
> On 27/05/2013, at 8:31 PM, Arnd Bergmann <[email protected]> wrote:
>
> > On Monday 27 May 2013, Daniel Tang wrote:
> >>> The one remaining bit that sticks out is the clcd platform data. As I
> >>> said before, I won't require you to convert that to DT in order to
> >>> get your code merged, but I'd also really like to see that happen,
> >>> as we will also need that to get rid of auxdata on the ARM reference
> >>> platforms (integrator, versatile, realview, vexpress).
> >>
> >> How would you like me to convert the platform data to DT? AFAIK, the clcd
> >> driver isn't aware of DT so the only way is to use the AUXDATA right now.
> >
> > Linus Walleij mentioned on IRC that Pawel Moll already posted a series
> > that adds DT support for clcd:
> >
> > http://lists.freedesktop.org/archives/dri-devel/2013-April/037519.html
> >
> > The series does a few more things, but you can probbly split out the
> > parts you need and base on that.
>
> Would it be fine if I waited until CLCD DT patch gets into mainline instead?
Yes, you can do that too, I was only asking whether you were interested
in helping out here.
Arnd
On Sat, 25 May 2013 21:08:07 +1000, Daniel Tang <[email protected]> wrote:
> Add support for the interrupt controller on TI-Nspires.
>
> Signed-off-by: Daniel Tang <[email protected]>
[...]
> +static void nspire_irq_ack(struct irq_data *irqd)
> +{
> + void __iomem *base = irq_io_base;
> +
> + if (irqd->hwirq < FIQ_START)
> + base += IO_IRQ_BASE;
> + else
> + base += IO_FIQ_BASE;
> +
> + readl(base + IO_RESET);
> +}
> +
> +static void nspire_irq_unmask(struct irq_data *irqd)
> +{
> + void __iomem *base = irq_io_base;
> + int irqnr = irqd->hwirq;
> +
> + if (irqnr < FIQ_START) {
> + base += IO_IRQ_BASE;
> + } else {
> + irqnr -= MAX_INTRS;
> + base += IO_FIQ_BASE;
> + }
> +
> + writel((1<<irqnr), base + IO_ENABLE);
> +}
> +
> +static void nspire_irq_mask(struct irq_data *irqd)
> +{
> + void __iomem *base = irq_io_base;
> + int irqnr = irqd->hwirq;
> +
> + if (irqnr < FIQ_START) {
> + base += IO_IRQ_BASE;
> + } else {
> + irqnr -= FIQ_START;
> + base += IO_FIQ_BASE;
> + }
> +
> + writel((1<<irqnr), base + IO_DISABLE);
> +}
> +
> +static struct irq_chip nspire_irq_chip = {
> + .name = "nspire_irq",
> + .irq_ack = nspire_irq_ack,
> + .irq_mask = nspire_irq_mask,
> + .irq_unmask = nspire_irq_unmask,
> +};
Should be using irq_generic_chip here. There is no need to reimplement
the above ack, mask and unmask functions. You should find the
irq_alloc_domain_generic_chips() patch in the tip tree irq/for-arm
branch. That branch is staged for merging in v3.11
Otherwise the patch looks good.
g.
Quoting Daniel Tang (2013-05-25 04:08:04)
> diff --git a/drivers/clk/clk-nspire.c b/drivers/clk/clk-nspire.c
> new file mode 100644
> index 0000000..2546f7d
> --- /dev/null
> +++ b/drivers/clk/clk-nspire.c
> @@ -0,0 +1,155 @@
> +/*
> + * linux/drivers/clk/clk-nspire.c
Hi Daniel,
It's best not to put any file path here, since it could change in the
future. Please remove it.
> + *
> + * Copyright (C) 2013 Daniel Tang <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2, as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +#define MHZ (1000 * 1000)
> +
> +#define BASE_CPU_SHIFT 1
> +#define BASE_CPU_MASK 0x7F
> +
> +#define CPU_AHB_SHIFT 12
> +#define CPU_AHB_MASK 0x07
> +
> +#define FIXED_BASE_SHIFT 8
> +#define FIXED_BASE_MASK 0x01
> +
> +#define CLASSIC_BASE_SHIFT 16
> +#define CLASSIC_BASE_MASK 0x1F
> +
> +#define CX_BASE_SHIFT 15
> +#define CX_BASE_MASK 0x3F
> +
> +#define CX_UNKNOWN_SHIFT 21
> +#define CX_UNKNOWN_MASK 0x03
> +
> +struct nspire_clk_info {
> + u32 base_clock;
> + u16 base_cpu_ratio;
> + u16 base_ahb_ratio;
> +};
> +
> +
> +#define EXTRACT(var, prop) (((var)>>prop##_SHIFT) & prop##_MASK)
> +static void nspire_clkinfo_cx(u32 val, struct nspire_clk_info *clk)
> +{
> + if (EXTRACT(val, FIXED_BASE))
> + clk->base_clock = 48 * MHZ;
> + else
> + clk->base_clock = 6 * EXTRACT(val, CX_BASE) * MHZ;
> +
> + clk->base_cpu_ratio = EXTRACT(val, BASE_CPU) * EXTRACT(val, CX_UNKNOWN);
> + clk->base_ahb_ratio = clk->base_cpu_ratio * (EXTRACT(val, CPU_AHB) + 1);
> +}
> +
> +static void nspire_clkinfo_classic(u32 val, struct nspire_clk_info *clk)
> +{
> + if (EXTRACT(val, FIXED_BASE))
> + clk->base_clock = 27 * MHZ;
> + else
> + clk->base_clock = (300 - 6 * EXTRACT(val, CLASSIC_BASE)) * MHZ;
> +
> + clk->base_cpu_ratio = EXTRACT(val, BASE_CPU) * 2;
> + clk->base_ahb_ratio = clk->base_cpu_ratio * (EXTRACT(val, CPU_AHB) + 1);
> +}
> +#undef EXTRACT
Any particular reason for the undef?
Rest looks good to me. If you can respin this patch I'll take it into
clk-next.
Thanks,
Mike
Hi Pawel,
Sorry for the late reply, I'm currently attending LinuxCon Japan, my mail
backlog is growing.
On Tuesday 28 May 2013 11:52:52 Pawel Moll wrote:
> On Mon, 2013-05-27 at 11:31 +0100, Arnd Bergmann wrote:
> > On Monday 27 May 2013, Daniel Tang wrote:
> > > > The one remaining bit that sticks out is the clcd platform data. As I
> > > > said before, I won't require you to convert that to DT in order to
> > > > get your code merged, but I'd also really like to see that happen,
> > > > as we will also need that to get rid of auxdata on the ARM reference
> > > > platforms (integrator, versatile, realview, vexpress).
> > >
> > > How would you like me to convert the platform data to DT? AFAIK, the
> > > clcd driver isn't aware of DT so the only way is to use the AUXDATA
> > > right now.
> >
> > Linus Walleij mentioned on IRC that Pawel Moll already posted a series
> > that adds DT support for clcd:
> >
> > http://lists.freedesktop.org/archives/dri-devel/2013-April/037519.html
> >
> > The series does a few more things, but you can probbly split out the
> > parts you need and base on that.
>
> The main "issue" with the series is its dependency on Laurent Pinchart's
> Common Display Framework (or rather on the progress of its upstreaming).
> I'm planning to discuss this in details in during the Linaro Connect in
> Dublin, but generally, if it's not getting merged in the next window,
> I'll spin the series to use the standard video modes bindings instead of
> CDF. This will make me hurt on Versatile Express, but should work for
> others.
I've met with Tomi Valkeinen (TI), Alexandre Courbot (NVidia) and Tomasz Figa
(Samsung) recently, For the first time the meetings helped narrowing the
options *down*. It seems a path is slowly unfolding, and I would like to
target v3.13 for a first (possibly limited) version.
Regarding the DT bindings, Alexandre and Tomasz will look into the V4L2 DT
bindings to see whether/how they can be reused/leveraged for the CDF bindings.
In both case we need to describe a graph of connected entities, and there's
not much in the V4L2 DT bindings that is V4L2-specific in that regard.
--
Regards,
Laurent Pinchart