forked from Minki/linux
First cleanup series for 3.15
- localize GPIO header in mach-at91 directory - big update on the CCF front with main and slow clocks - a cleanup of ADC and touchscreen driver with unification on IIO and removal of old driver -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQEcBAABAgAGBQJTamtjAAoJEAf03oE53VmQ0A4IAL1ir8w5bMCkrQL67jWSnCVm dmmOsajAX4hqmXSYZrBv/eBfghM8FO/z8v8LguDpO/b1lXU97Bm1S256X6gBfcC7 25a0sdaUvwiXfj77r323oGlvs2MKFAkMZ85ERNVhjmluBT58Yk7/fpiRY4pS6vzg L2Gp3INixXYMxcniiel+blGPFyp6IAWIxZs09e7SkUIEqTu4DZu9PijmuoW/66Uu dIstLZigDf1naUevRvf1ebIONoPwx8EF502n97NaVsmNRooA2hnuPKQ6Fc9WptYy ih9sGw/HIhPmsPwAOcrYrlMglOVft6k8bMEPpf0vKKlP54MJI8NPf4rfqNzT+4k= =pk+7 -----END PGP SIGNATURE----- Merge tag 'at91-cleanup' of git://github.com/at91linux/linux-at91 into next/soc Merge "at91: cleanup for 3.16 #1" from Nicolas Ferre: First cleanup series for 3.15 - localize GPIO header in mach-at91 directory - big update on the CCF front with main and slow clocks - a cleanup of ADC and touchscreen driver with unification on IIO and removal of old driver [olof: Most of this branch is new code, not cleanups, so I'm merging this into the SoC branch in spite of the branch name] * tag 'at91-cleanup' of git://github.com/at91linux/linux-at91: (28 commits) ARM: at91/dt: at91-cosino_mega2560 remove useless tsadcc node ARM: at91: remove atmel_tsadcc platform_data Input: atmel_tsadcc: remove driver ARM: at91: remove atmel_tsadcc from sama5_defconfig ARM: at91: sam9rl: switch from atmel_tsadcc to at91_adc ARM: at91: sam9g45: switch from atmel_tsadcc to at91_adc ARM: at91: sam9rlek add touchscreen support through at91_adc ARM: at91: sam9rl: add at91_adc to support adc and touchscreen iio: adc: at91: add sam9rl support iio: adc: at91: remove unused include from include/mach ARM: at91: sam9m10g45ek: Add touchscreen support through at91_adc iio: adc: at91_adc: Add support for touchscreens without TSMR iio: adc: at91: cleanup platform_data ARM: at91: sam9260: remove unused platform_data ARM: at91: sam9g45: remove unused platform_data ARM: at91/dt: define sam9rlek crystal frequencies ARM: at91/dt: move at91sam9rl SoC to the new slow/main clock models ARM: at91/dt: define main xtal frequency of the at91sam9261ek board ARM: at91/dt: move at91sam9261 SoC to the new main clock model ARM: at91/dt: add xtal frequencies to sama5d3 xplained board ... Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
05983ed4a3
@ -6,6 +6,16 @@ This binding uses the common clock binding[1].
|
||||
|
||||
Required properties:
|
||||
- compatible : shall be one of the following:
|
||||
"atmel,at91sam9x5-sckc":
|
||||
at91 SCKC (Slow Clock Controller)
|
||||
This node contains the slow clock definitions.
|
||||
|
||||
"atmel,at91sam9x5-clk-slow-osc":
|
||||
at91 slow oscillator
|
||||
|
||||
"atmel,at91sam9x5-clk-slow-rc-osc":
|
||||
at91 internal slow RC oscillator
|
||||
|
||||
"atmel,at91rm9200-pmc" or
|
||||
"atmel,at91sam9g45-pmc" or
|
||||
"atmel,at91sam9n12-pmc" or
|
||||
@ -15,8 +25,18 @@ Required properties:
|
||||
All at91 specific clocks (clocks defined below) must be child
|
||||
node of the PMC node.
|
||||
|
||||
"atmel,at91sam9x5-clk-slow" (under sckc node)
|
||||
or
|
||||
"atmel,at91sam9260-clk-slow" (under pmc node):
|
||||
at91 slow clk
|
||||
|
||||
"atmel,at91rm9200-clk-main-osc"
|
||||
"atmel,at91sam9x5-clk-main-rc-osc"
|
||||
at91 main clk sources
|
||||
|
||||
"atmel,at91sam9x5-clk-main"
|
||||
"atmel,at91rm9200-clk-main":
|
||||
at91 main oscillator
|
||||
at91 main clock
|
||||
|
||||
"atmel,at91rm9200-clk-master" or
|
||||
"atmel,at91sam9x5-clk-master":
|
||||
@ -54,6 +74,63 @@ Required properties:
|
||||
"atmel,at91sam9x5-clk-utmi":
|
||||
at91 utmi clock
|
||||
|
||||
Required properties for SCKC node:
|
||||
- reg : defines the IO memory reserved for the SCKC.
|
||||
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||
- #address-cells : shall be 1 (reg is used to encode clk id).
|
||||
|
||||
|
||||
For example:
|
||||
sckc: sckc@fffffe50 {
|
||||
compatible = "atmel,sama5d3-pmc";
|
||||
reg = <0xfffffe50 0x4>
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
|
||||
/* put at91 slow clocks here */
|
||||
};
|
||||
|
||||
|
||||
Required properties for internal slow RC oscillator:
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clock-frequency : define the internal RC oscillator frequency.
|
||||
|
||||
Optional properties:
|
||||
- clock-accuracy : define the internal RC oscillator accuracy.
|
||||
|
||||
For example:
|
||||
slow_rc_osc: slow_rc_osc {
|
||||
compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
|
||||
clock-frequency = <32768>;
|
||||
clock-accuracy = <50000000>;
|
||||
};
|
||||
|
||||
Required properties for slow oscillator:
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall encode the main osc source clk sources (see atmel datasheet).
|
||||
|
||||
Optional properties:
|
||||
- atmel,osc-bypass : boolean property. Set this when a clock signal is directly
|
||||
provided on XIN.
|
||||
|
||||
For example:
|
||||
slow_osc: slow_osc {
|
||||
compatible = "atmel,at91rm9200-clk-slow-osc";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&slow_xtal>;
|
||||
};
|
||||
|
||||
Required properties for slow clock:
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall encode the slow clk sources (see atmel datasheet).
|
||||
|
||||
For example:
|
||||
clk32k: slck {
|
||||
compatible = "atmel,at91sam9x5-clk-slow";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&slow_rc_osc &slow_osc>;
|
||||
};
|
||||
|
||||
Required properties for PMC node:
|
||||
- reg : defines the IO memory reserved for the PMC.
|
||||
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||
@ -85,24 +162,57 @@ For example:
|
||||
/* put at91 clocks here */
|
||||
};
|
||||
|
||||
Required properties for main clock internal RC oscillator:
|
||||
- interrupt-parent : must reference the PMC node.
|
||||
- interrupts : shall be set to "<0>".
|
||||
- clock-frequency : define the internal RC oscillator frequency.
|
||||
|
||||
Optional properties:
|
||||
- clock-accuracy : define the internal RC oscillator accuracy.
|
||||
|
||||
For example:
|
||||
main_rc_osc: main_rc_osc {
|
||||
compatible = "atmel,at91sam9x5-clk-main-rc-osc";
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <0>;
|
||||
clock-frequency = <12000000>;
|
||||
clock-accuracy = <50000000>;
|
||||
};
|
||||
|
||||
Required properties for main clock oscillator:
|
||||
- interrupt-parent : must reference the PMC node.
|
||||
- interrupts : shall be set to "<0>".
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks : shall encode the main osc source clk sources (see atmel datasheet).
|
||||
|
||||
Optional properties:
|
||||
- atmel,osc-bypass : boolean property. Specified if a clock signal is provided
|
||||
on XIN.
|
||||
|
||||
clock signal is directly provided on XIN pin.
|
||||
|
||||
For example:
|
||||
main_osc: main_osc {
|
||||
compatible = "atmel,at91rm9200-clk-main-osc";
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <0>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&main_xtal>;
|
||||
};
|
||||
|
||||
Required properties for main clock:
|
||||
- interrupt-parent : must reference the PMC node.
|
||||
- interrupts : shall be set to "<0>".
|
||||
- #clock-cells : from common clock binding; shall be set to 0.
|
||||
- clocks (optional if clock-frequency is provided) : shall be the slow clock
|
||||
phandle. This clock is used to calculate the main clock rate if
|
||||
"clock-frequency" is not provided.
|
||||
- clock-frequency : the main oscillator frequency.Prefer the use of
|
||||
"clock-frequency" over automatic clock rate calculation.
|
||||
- clocks : shall encode the main clk sources (see atmel datasheet).
|
||||
|
||||
For example:
|
||||
main: mainck {
|
||||
compatible = "atmel,at91rm9200-clk-main";
|
||||
compatible = "atmel,at91sam9x5-clk-main";
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <0>;
|
||||
#clock-cells = <0>;
|
||||
clocks = <&ck32k>;
|
||||
clock-frequency = <18432000>;
|
||||
clocks = <&main_rc_osc &main_osc>;
|
||||
};
|
||||
|
||||
Required properties for master clock:
|
||||
|
@ -1617,12 +1617,6 @@ S: Supported
|
||||
F: drivers/misc/atmel_tclib.c
|
||||
F: drivers/clocksource/tcb_clksrc.c
|
||||
|
||||
ATMEL TSADCC DRIVER
|
||||
M: Josh Wu <josh.wu@atmel.com>
|
||||
L: linux-input@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/input/touchscreen/atmel_tsadcc.c
|
||||
|
||||
ATMEL USBA UDC DRIVER
|
||||
M: Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
@ -376,7 +376,6 @@ config ARCH_AT91
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select CLKDEV_LOOKUP
|
||||
select IRQ_DOMAIN
|
||||
select NEED_MACH_GPIO_H
|
||||
select NEED_MACH_IO_H if PCCARD
|
||||
select PINCTRL
|
||||
select PINCTRL_AT91 if USE_OF
|
||||
|
@ -32,11 +32,6 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
tsadcc: tsadcc@f804c000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
rtc@fffffeb0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -21,6 +21,14 @@
|
||||
reg = <0x20000000 0x10000000>;
|
||||
};
|
||||
|
||||
slow_xtal {
|
||||
clock-frequency = <32768>;
|
||||
};
|
||||
|
||||
main_xtal {
|
||||
clock-frequency = <12000000>;
|
||||
};
|
||||
|
||||
ahb {
|
||||
apb {
|
||||
mmc0: mmc@f0000000 {
|
||||
|
@ -45,6 +45,18 @@
|
||||
reg = <0x20000000 0x08000000>;
|
||||
};
|
||||
|
||||
main_xtal: main_xtal {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
slow_xtal: slow_xtal {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
ahb {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
@ -524,17 +536,24 @@
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
clk32k: slck {
|
||||
slow_rc_osc: slow_rc_osc {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <32768>;
|
||||
clock-accuracy = <50000000>;
|
||||
};
|
||||
|
||||
clk32k: slck {
|
||||
compatible = "atmel,at91sam9260-clk-slow";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&slow_rc_osc &slow_xtal>;
|
||||
};
|
||||
|
||||
main: mainck {
|
||||
compatible = "atmel,at91rm9200-clk-main";
|
||||
#clock-cells = <0>;
|
||||
interrupts-extended = <&pmc AT91_PMC_MOSCS>;
|
||||
clocks = <&clk32k>;
|
||||
clocks = <&main_xtal>;
|
||||
};
|
||||
|
||||
plla: pllack {
|
||||
|
@ -20,6 +20,10 @@
|
||||
reg = <0x20000000 0x4000000>;
|
||||
};
|
||||
|
||||
main_xtal {
|
||||
clock-frequency = <18432000>;
|
||||
};
|
||||
|
||||
clocks {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
@ -48,6 +48,18 @@
|
||||
reg = <0x20000000 0x04000000>;
|
||||
};
|
||||
|
||||
slow_xtal: slow_xtal {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
main_xtal: main_xtal {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
ahb {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
@ -548,17 +560,11 @@
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
clk32k: slck {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <32768>;
|
||||
};
|
||||
|
||||
main: mainck {
|
||||
compatible = "atmel,at91rm9200-clk-main";
|
||||
#clock-cells = <0>;
|
||||
interrupts-extended = <&pmc AT91_PMC_MOSCS>;
|
||||
clocks = <&clk32k>;
|
||||
clocks = <&main_xtal>;
|
||||
};
|
||||
|
||||
plla: pllack {
|
||||
@ -769,6 +775,32 @@
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sckc@fffffd50 {
|
||||
compatible = "atmel,at91sam9x5-sckc";
|
||||
reg = <0xfffffd50 0x4>;
|
||||
|
||||
slow_osc: slow_osc {
|
||||
compatible = "atmel,at91sam9x5-clk-slow-osc";
|
||||
#clock-cells = <0>;
|
||||
atmel,startup-time-usec = <1200000>;
|
||||
clocks = <&slow_xtal>;
|
||||
};
|
||||
|
||||
slow_rc_osc: slow_rc_osc {
|
||||
compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
|
||||
#clock-cells = <0>;
|
||||
atmel,startup-time-usec = <75>;
|
||||
clock-frequency = <32768>;
|
||||
clock-accuracy = <50000000>;
|
||||
};
|
||||
|
||||
clk32k: slck {
|
||||
compatible = "atmel,at91sam9x5-clk-slow";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&slow_rc_osc &slow_osc>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,15 @@
|
||||
reg = <0x20000000 0x4000000>;
|
||||
};
|
||||
|
||||
|
||||
slow_xtal {
|
||||
clock-frequency = <32768>;
|
||||
};
|
||||
|
||||
main_xtal {
|
||||
clock-frequency = <12000000>;
|
||||
};
|
||||
|
||||
clocks {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
@ -58,6 +58,18 @@
|
||||
reg = <0x20000000 0x8000000>;
|
||||
};
|
||||
|
||||
slow_xtal: slow_xtal {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
main_xtal: main_xtal {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <0>;
|
||||
};
|
||||
|
||||
clocks {
|
||||
adc_op_clk: adc_op_clk{
|
||||
compatible = "fixed-clock";
|
||||
@ -749,18 +761,29 @@
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
clk32k: slck {
|
||||
compatible = "fixed-clock";
|
||||
main_rc_osc: main_rc_osc {
|
||||
compatible = "atmel,at91sam9x5-clk-main-rc-osc";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <32768>;
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <AT91_PMC_MOSCRCS>;
|
||||
clock-frequency = <12000000>;
|
||||
clock-accuracy = <50000000>;
|
||||
};
|
||||
|
||||
main: mainck {
|
||||
compatible = "atmel,at91rm9200-clk-main";
|
||||
main_osc: main_osc {
|
||||
compatible = "atmel,at91rm9200-clk-main-osc";
|
||||
#clock-cells = <0>;
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <AT91_PMC_MOSCS>;
|
||||
clocks = <&clk32k>;
|
||||
clocks = <&main_xtal>;
|
||||
};
|
||||
|
||||
main: mainck {
|
||||
compatible = "atmel,at91sam9x5-clk-main";
|
||||
#clock-cells = <0>;
|
||||
interrupt-parent = <&pmc>;
|
||||
interrupts = <AT91_PMC_MOSCSELS>;
|
||||
clocks = <&main_rc_osc &main_osc>;
|
||||
};
|
||||
|
||||
plla: pllack {
|
||||
@ -1089,6 +1112,32 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sckc@fffffe50 {
|
||||
compatible = "atmel,at91sam9x5-sckc";
|
||||
reg = <0xfffffe50 0x4>;
|
||||
|
||||
slow_rc_osc: slow_rc_osc {
|
||||
compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <32768>;
|
||||
clock-accuracy = <50000000>;
|
||||
atmel,startup-time-usec = <75>;
|
||||
};
|
||||
|
||||
slow_osc: slow_osc {
|
||||
compatible = "atmel,at91sam9x5-clk-slow-osc";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&slow_xtal>;
|
||||
atmel,startup-time-usec = <1200000>;
|
||||
};
|
||||
|
||||
clk32k: slowck {
|
||||
compatible = "atmel,at91sam9x5-clk-slow";
|
||||
#clock-cells = <0>;
|
||||
clocks = <&slow_rc_osc &slow_osc>;
|
||||
};
|
||||
};
|
||||
|
||||
rtc@fffffeb0 {
|
||||
compatible = "atmel,at91rm9200-rtc";
|
||||
reg = <0xfffffeb0 0x30>;
|
||||
|
@ -18,6 +18,14 @@
|
||||
reg = <0x20000000 0x20000000>;
|
||||
};
|
||||
|
||||
slow_xtal {
|
||||
clock-frequency = <32768>;
|
||||
};
|
||||
|
||||
main_xtal {
|
||||
clock-frequency = <12000000>;
|
||||
};
|
||||
|
||||
ahb {
|
||||
apb {
|
||||
spi0: spi@f0004000 {
|
||||
|
@ -83,7 +83,6 @@ CONFIG_KEYBOARD_GPIO=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
CONFIG_INPUT_TOUCHSCREEN=y
|
||||
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
|
||||
CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
CONFIG_SERIAL_ATMEL=y
|
||||
@ -146,6 +145,8 @@ CONFIG_DMADEVICES=y
|
||||
CONFIG_AT_HDMAC=y
|
||||
CONFIG_DMATEST=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_IIO=y
|
||||
CONFIG_AT91_ADC=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_FANOTIFY=y
|
||||
CONFIG_VFAT_FS=y
|
||||
|
@ -45,7 +45,6 @@ CONFIG_INPUT_EVDEV=y
|
||||
# CONFIG_INPUT_KEYBOARD is not set
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
CONFIG_INPUT_TOUCHSCREEN=y
|
||||
CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
|
||||
# CONFIG_SERIO is not set
|
||||
CONFIG_SERIAL_ATMEL=y
|
||||
CONFIG_SERIAL_ATMEL_CONSOLE=y
|
||||
@ -65,6 +64,8 @@ CONFIG_MMC=y
|
||||
CONFIG_MMC_ATMELMCI=m
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_AT91SAM9=y
|
||||
CONFIG_IIO=y
|
||||
CONFIG_AT91_ADC=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
|
@ -122,7 +122,6 @@ CONFIG_KEYBOARD_GPIO=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
CONFIG_INPUT_TOUCHSCREEN=y
|
||||
CONFIG_TOUCHSCREEN_ATMEL_MXT=y
|
||||
CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
|
||||
# CONFIG_SERIO is not set
|
||||
CONFIG_LEGACY_PTY_COUNT=4
|
||||
CONFIG_SERIAL_ATMEL=y
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
|
@ -24,12 +24,11 @@
|
||||
#include <mach/at91sam9260_matrix.h>
|
||||
#include <mach/at91_matrix.h>
|
||||
#include <mach/at91sam9_smc.h>
|
||||
#include <mach/at91_adc.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* USB Host
|
||||
@ -1325,13 +1324,6 @@ static struct at91_adc_trigger at91_adc_triggers[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct at91_adc_reg_desc at91_adc_register_g20 = {
|
||||
.channel_base = AT91_ADC_CHR(0),
|
||||
.drdy_mask = AT91_ADC_DRDY,
|
||||
.status_register = AT91_ADC_SR,
|
||||
.trigger_register = AT91_ADC_MR,
|
||||
};
|
||||
|
||||
void __init at91_add_device_adc(struct at91_adc_data *data)
|
||||
{
|
||||
if (!data)
|
||||
@ -1349,9 +1341,7 @@ void __init at91_add_device_adc(struct at91_adc_data *data)
|
||||
if (data->use_external_triggers)
|
||||
at91_set_A_periph(AT91_PIN_PA22, 0);
|
||||
|
||||
data->num_channels = 4;
|
||||
data->startup_time = 10;
|
||||
data->registers = &at91_adc_register_g20;
|
||||
data->trigger_number = 4;
|
||||
data->trigger_list = at91_adc_triggers;
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* USB Host
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
|
@ -182,7 +182,7 @@ static struct clk vdec_clk = {
|
||||
static struct clk adc_op_clk = {
|
||||
.name = "adc_op_clk",
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
.rate_hz = 13200000,
|
||||
.rate_hz = 300000,
|
||||
};
|
||||
|
||||
/* AES/TDES/SHA clock - Only for sam9m11/sam9g56 */
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <linux/fb.h>
|
||||
#include <video/atmel_lcdc.h>
|
||||
|
||||
#include <mach/at91_adc.h>
|
||||
#include <mach/at91sam9g45.h>
|
||||
#include <mach/at91sam9g45_matrix.h>
|
||||
#include <mach/at91_matrix.h>
|
||||
@ -39,6 +38,7 @@
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "clock.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
@ -1133,58 +1133,7 @@ static void __init at91_add_device_rtc(void) {}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Touchscreen
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
|
||||
static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
|
||||
static struct at91_tsadcc_data tsadcc_data;
|
||||
|
||||
static struct resource tsadcc_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91SAM9G45_BASE_TSC,
|
||||
.end = AT91SAM9G45_BASE_TSC + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
|
||||
.end = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device at91sam9g45_tsadcc_device = {
|
||||
.name = "atmel_tsadcc",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &tsadcc_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &tsadcc_data,
|
||||
},
|
||||
.resource = tsadcc_resources,
|
||||
.num_resources = ARRAY_SIZE(tsadcc_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
at91_set_gpio_input(AT91_PIN_PD20, 0); /* AD0_XR */
|
||||
at91_set_gpio_input(AT91_PIN_PD21, 0); /* AD1_XL */
|
||||
at91_set_gpio_input(AT91_PIN_PD22, 0); /* AD2_YT */
|
||||
at91_set_gpio_input(AT91_PIN_PD23, 0); /* AD3_TB */
|
||||
|
||||
tsadcc_data = *data;
|
||||
platform_device_register(&at91sam9g45_tsadcc_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* ADC
|
||||
* ADC and touchscreen
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if IS_ENABLED(CONFIG_AT91_ADC)
|
||||
@ -1236,13 +1185,6 @@ static struct at91_adc_trigger at91_adc_triggers[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct at91_adc_reg_desc at91_adc_register_g45 = {
|
||||
.channel_base = AT91_ADC_CHR(0),
|
||||
.drdy_mask = AT91_ADC_DRDY,
|
||||
.status_register = AT91_ADC_SR,
|
||||
.trigger_register = 0x08,
|
||||
};
|
||||
|
||||
void __init at91_add_device_adc(struct at91_adc_data *data)
|
||||
{
|
||||
if (!data)
|
||||
@ -1268,9 +1210,7 @@ void __init at91_add_device_adc(struct at91_adc_data *data)
|
||||
if (data->use_external_triggers)
|
||||
at91_set_A_periph(AT91_PIN_PD28, 0);
|
||||
|
||||
data->num_channels = 8;
|
||||
data->startup_time = 40;
|
||||
data->registers = &at91_adc_register_g45;
|
||||
data->trigger_number = 4;
|
||||
data->trigger_list = at91_adc_triggers;
|
||||
|
||||
|
@ -153,6 +153,11 @@ static struct clk ac97_clk = {
|
||||
.pmc_mask = 1 << AT91SAM9RL_ID_AC97C,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk adc_op_clk = {
|
||||
.name = "adc_op_clk",
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
.rate_hz = 1000000,
|
||||
};
|
||||
|
||||
static struct clk *periph_clocks[] __initdata = {
|
||||
&pioA_clk,
|
||||
@ -178,6 +183,7 @@ static struct clk *periph_clocks[] __initdata = {
|
||||
&udphs_clk,
|
||||
&lcdc_clk,
|
||||
&ac97_clk,
|
||||
&adc_op_clk,
|
||||
// irq0
|
||||
};
|
||||
|
||||
@ -216,6 +222,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
|
||||
CLKDEV_CON_DEV_ID(NULL, "fffff600.gpio", &pioB_clk),
|
||||
CLKDEV_CON_DEV_ID(NULL, "fffff800.gpio", &pioC_clk),
|
||||
CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioD_clk),
|
||||
CLKDEV_CON_ID("adc_clk", &tsc_clk),
|
||||
};
|
||||
|
||||
static struct clk_lookup usart_clocks_lookups[] = {
|
||||
|
@ -23,9 +23,11 @@
|
||||
#include <mach/at91sam9_smc.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <linux/platform_data/dma-atmel.h>
|
||||
#include <linux/platform_data/at91_adc.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
@ -608,14 +610,13 @@ static void __init at91_add_device_tc(void) { }
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Touchscreen
|
||||
* ADC and Touchscreen
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
|
||||
static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
|
||||
static struct at91_tsadcc_data tsadcc_data;
|
||||
#if IS_ENABLED(CONFIG_AT91_ADC)
|
||||
static struct at91_adc_data adc_data;
|
||||
|
||||
static struct resource tsadcc_resources[] = {
|
||||
static struct resource adc_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91SAM9RL_BASE_TSC,
|
||||
.end = AT91SAM9RL_BASE_TSC + SZ_16K - 1,
|
||||
@ -628,36 +629,71 @@ static struct resource tsadcc_resources[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device at91sam9rl_tsadcc_device = {
|
||||
.name = "atmel_tsadcc",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &tsadcc_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &tsadcc_data,
|
||||
static struct platform_device at91_adc_device = {
|
||||
.name = "at91sam9rl-adc",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &adc_data,
|
||||
},
|
||||
.resource = tsadcc_resources,
|
||||
.num_resources = ARRAY_SIZE(tsadcc_resources),
|
||||
.resource = adc_resources,
|
||||
.num_resources = ARRAY_SIZE(adc_resources),
|
||||
};
|
||||
|
||||
void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
|
||||
static struct at91_adc_trigger at91_adc_triggers[] = {
|
||||
[0] = {
|
||||
.name = "external-rising",
|
||||
.value = 1,
|
||||
.is_external = true,
|
||||
},
|
||||
[1] = {
|
||||
.name = "external-falling",
|
||||
.value = 2,
|
||||
.is_external = true,
|
||||
},
|
||||
[2] = {
|
||||
.name = "external-any",
|
||||
.value = 3,
|
||||
.is_external = true,
|
||||
},
|
||||
[3] = {
|
||||
.name = "continuous",
|
||||
.value = 6,
|
||||
.is_external = false,
|
||||
},
|
||||
};
|
||||
|
||||
void __init at91_add_device_adc(struct at91_adc_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
at91_set_A_periph(AT91_PIN_PA17, 0); /* AD0_XR */
|
||||
at91_set_A_periph(AT91_PIN_PA18, 0); /* AD1_XL */
|
||||
at91_set_A_periph(AT91_PIN_PA19, 0); /* AD2_YT */
|
||||
at91_set_A_periph(AT91_PIN_PA20, 0); /* AD3_TB */
|
||||
if (test_bit(0, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PA17, 0);
|
||||
if (test_bit(1, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PA18, 0);
|
||||
if (test_bit(2, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PA19, 0);
|
||||
if (test_bit(3, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PA20, 0);
|
||||
if (test_bit(4, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PD6, 0);
|
||||
if (test_bit(5, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PD7, 0);
|
||||
|
||||
tsadcc_data = *data;
|
||||
platform_device_register(&at91sam9rl_tsadcc_device);
|
||||
if (data->use_external_triggers)
|
||||
at91_set_A_periph(AT91_PIN_PB15, 0);
|
||||
|
||||
data->startup_time = 40;
|
||||
data->trigger_number = 4;
|
||||
data->trigger_list = at91_adc_triggers;
|
||||
|
||||
adc_data = *data;
|
||||
platform_device_register(&at91_adc_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
|
||||
void __init at91_add_device_adc(struct at91_adc_data *data) {}
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* RTC
|
||||
* -------------------------------------------------------------------- */
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
static void __init onearm_init_early(void)
|
||||
{
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init afeb9260_init_early(void)
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init cam60_init_early(void)
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init carmeva_init_early(void)
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
static void __init cpu9krea_init_early(void)
|
||||
{
|
||||
|
@ -43,6 +43,8 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static struct gpio_led cpuat91_leds[] = {
|
||||
{
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
static void __init csb337_init_early(void)
|
||||
{
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init csb637_init_early(void)
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init eb9200_init_early(void)
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init ecb_at91init_early(void)
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init eco920_init_early(void)
|
||||
{
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
static void __init flexibity_init_early(void)
|
||||
{
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/*
|
||||
* The FOX Board G20 hardware comes as the "Netus G20" board with
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "generic.h"
|
||||
#include "gsia18s.h"
|
||||
#include "stamp9g20.h"
|
||||
#include "gpio.h"
|
||||
|
||||
static void __init gsia18s_init_early(void)
|
||||
{
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init kafa_init_early(void)
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init kb9202_init_early(void)
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "stamp9g20.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init pcontrol_g20_init_early(void)
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init picotux200_init_early(void)
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init ek_init_early(void)
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
static void __init rsi_ews_init_early(void)
|
||||
{
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init ek_init_early(void)
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init ek_init_early(void)
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init ek_init_early(void)
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init ek_init_early(void)
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/*
|
||||
* board revision encoding
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init ek_init_early(void)
|
||||
@ -300,21 +301,13 @@ static struct atmel_lcdfb_pdata __initdata ek_lcdc_data;
|
||||
|
||||
|
||||
/*
|
||||
* Touchscreen
|
||||
*/
|
||||
static struct at91_tsadcc_data ek_tsadcc_data = {
|
||||
.adc_clock = 300000,
|
||||
.pendet_debounce = 0x0d,
|
||||
.ts_sample_hold_time = 0x0a,
|
||||
};
|
||||
|
||||
/*
|
||||
* ADCs
|
||||
* ADCs and touchscreen
|
||||
*/
|
||||
static struct at91_adc_data ek_adc_data = {
|
||||
.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7),
|
||||
.use_external_triggers = true,
|
||||
.vref = 3300,
|
||||
.touchscreen_type = ATMEL_ADC_TOUCHSCREEN_4WIRE,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -485,9 +478,7 @@ static void __init ek_board_init(void)
|
||||
at91_add_device_isi(&isi_data, true);
|
||||
/* LCD Controller */
|
||||
at91_add_device_lcdc(&ek_lcdc_data);
|
||||
/* Touch Screen */
|
||||
at91_add_device_tsadcc(&ek_tsadcc_data);
|
||||
/* ADC */
|
||||
/* ADC and touchscreen */
|
||||
at91_add_device_adc(&ek_adc_data);
|
||||
/* Push Buttons */
|
||||
ek_add_device_buttons();
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/platform_data/at91_adc.h>
|
||||
|
||||
#include <video/atmel_lcdc.h>
|
||||
|
||||
@ -38,6 +39,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init ek_init_early(void)
|
||||
@ -229,12 +231,13 @@ static struct gpio_led ek_leds[] = {
|
||||
|
||||
|
||||
/*
|
||||
* Touchscreen
|
||||
* ADC + Touchscreen
|
||||
*/
|
||||
static struct at91_tsadcc_data ek_tsadcc_data = {
|
||||
.adc_clock = 1000000,
|
||||
.pendet_debounce = 0x0f,
|
||||
.ts_sample_hold_time = 0x03,
|
||||
static struct at91_adc_data ek_adc_data = {
|
||||
.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
|
||||
.use_external_triggers = true,
|
||||
.vref = 3300,
|
||||
.touchscreen_type = ATMEL_ADC_TOUCHSCREEN_4WIRE,
|
||||
};
|
||||
|
||||
|
||||
@ -310,8 +313,8 @@ static void __init ek_board_init(void)
|
||||
at91_add_device_lcdc(&ek_lcdc_data);
|
||||
/* AC97 */
|
||||
at91_add_device_ac97(&ek_ac97_data);
|
||||
/* Touch Screen Controller */
|
||||
at91_add_device_tsadcc(&ek_tsadcc_data);
|
||||
/* Touch Screen Controller + ADC */
|
||||
at91_add_device_adc(&ek_adc_data);
|
||||
/* LEDs */
|
||||
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
|
||||
/* Push Buttons */
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#define SNAPPER9260_IO_EXP_GPIO(x) (NR_BUILTIN_GPIO + (x))
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "board.h"
|
||||
#include "sam9_smc.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
void __init stamp9g20_init_early(void)
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "board.h"
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
static void __init yl9200_init_early(void)
|
||||
|
@ -118,9 +118,6 @@ struct isi_platform_data;
|
||||
extern void __init at91_add_device_isi(struct isi_platform_data *data,
|
||||
bool use_pck_as_mck);
|
||||
|
||||
/* Touchscreen Controller */
|
||||
extern void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data);
|
||||
|
||||
/* CAN */
|
||||
extern void __init at91_add_device_can(struct at91_can_data *data);
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <mach/at91_pio.h>
|
||||
|
||||
#include "generic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#define MAX_NB_GPIO_PER_BANK 32
|
||||
|
||||
|
@ -209,14 +209,6 @@ extern int at91_get_gpio_value(unsigned pin);
|
||||
extern void at91_gpio_suspend(void);
|
||||
extern void at91_gpio_resume(void);
|
||||
|
||||
#ifdef CONFIG_PINCTRL_AT91
|
||||
extern void at91_pinctrl_gpio_suspend(void);
|
||||
extern void at91_pinctrl_gpio_resume(void);
|
||||
#else
|
||||
static inline void at91_pinctrl_gpio_suspend(void) {}
|
||||
static inline void at91_pinctrl_gpio_resume(void) {}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-at91/include/mach/at91_adc.h
|
||||
*
|
||||
* Copyright (C) SAN People
|
||||
*
|
||||
* Analog-to-Digital Converter (ADC) registers.
|
||||
* Based on AT91SAM9260 datasheet revision D.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AT91_ADC_H
|
||||
#define AT91_ADC_H
|
||||
|
||||
#define AT91_ADC_CR 0x00 /* Control Register */
|
||||
#define AT91_ADC_SWRST (1 << 0) /* Software Reset */
|
||||
#define AT91_ADC_START (1 << 1) /* Start Conversion */
|
||||
|
||||
#define AT91_ADC_MR 0x04 /* Mode Register */
|
||||
#define AT91_ADC_TRGEN (1 << 0) /* Trigger Enable */
|
||||
#define AT91_ADC_TRGSEL (7 << 1) /* Trigger Selection */
|
||||
#define AT91_ADC_TRGSEL_TC0 (0 << 1)
|
||||
#define AT91_ADC_TRGSEL_TC1 (1 << 1)
|
||||
#define AT91_ADC_TRGSEL_TC2 (2 << 1)
|
||||
#define AT91_ADC_TRGSEL_EXTERNAL (6 << 1)
|
||||
#define AT91_ADC_LOWRES (1 << 4) /* Low Resolution */
|
||||
#define AT91_ADC_SLEEP (1 << 5) /* Sleep Mode */
|
||||
#define AT91_ADC_PRESCAL_9260 (0x3f << 8) /* Prescalar Rate Selection */
|
||||
#define AT91_ADC_PRESCAL_9G45 (0xff << 8)
|
||||
#define AT91_ADC_PRESCAL_(x) ((x) << 8)
|
||||
#define AT91_ADC_STARTUP_9260 (0x1f << 16) /* Startup Up Time */
|
||||
#define AT91_ADC_STARTUP_9G45 (0x7f << 16)
|
||||
#define AT91_ADC_STARTUP_9X5 (0xf << 16)
|
||||
#define AT91_ADC_STARTUP_(x) ((x) << 16)
|
||||
#define AT91_ADC_SHTIM (0xf << 24) /* Sample & Hold Time */
|
||||
#define AT91_ADC_SHTIM_(x) ((x) << 24)
|
||||
|
||||
#define AT91_ADC_CHER 0x10 /* Channel Enable Register */
|
||||
#define AT91_ADC_CHDR 0x14 /* Channel Disable Register */
|
||||
#define AT91_ADC_CHSR 0x18 /* Channel Status Register */
|
||||
#define AT91_ADC_CH(n) (1 << (n)) /* Channel Number */
|
||||
|
||||
#define AT91_ADC_SR 0x1C /* Status Register */
|
||||
#define AT91_ADC_EOC(n) (1 << (n)) /* End of Conversion on Channel N */
|
||||
#define AT91_ADC_OVRE(n) (1 << ((n) + 8))/* Overrun Error on Channel N */
|
||||
#define AT91_ADC_DRDY (1 << 16) /* Data Ready */
|
||||
#define AT91_ADC_GOVRE (1 << 17) /* General Overrun Error */
|
||||
#define AT91_ADC_ENDRX (1 << 18) /* End of RX Buffer */
|
||||
#define AT91_ADC_RXFUFF (1 << 19) /* RX Buffer Full */
|
||||
|
||||
#define AT91_ADC_SR_9X5 0x30 /* Status Register for 9x5 */
|
||||
#define AT91_ADC_SR_DRDY_9X5 (1 << 24) /* Data Ready */
|
||||
|
||||
#define AT91_ADC_LCDR 0x20 /* Last Converted Data Register */
|
||||
#define AT91_ADC_LDATA (0x3ff)
|
||||
|
||||
#define AT91_ADC_IER 0x24 /* Interrupt Enable Register */
|
||||
#define AT91_ADC_IDR 0x28 /* Interrupt Disable Register */
|
||||
#define AT91_ADC_IMR 0x2C /* Interrupt Mask Register */
|
||||
#define AT91_ADC_IER_PEN (1 << 29)
|
||||
#define AT91_ADC_IER_NOPEN (1 << 30)
|
||||
#define AT91_ADC_IER_XRDY (1 << 20)
|
||||
#define AT91_ADC_IER_YRDY (1 << 21)
|
||||
#define AT91_ADC_IER_PRDY (1 << 22)
|
||||
#define AT91_ADC_ISR_PENS (1 << 31)
|
||||
|
||||
#define AT91_ADC_CHR(n) (0x30 + ((n) * 4)) /* Channel Data Register N */
|
||||
#define AT91_ADC_DATA (0x3ff)
|
||||
|
||||
#define AT91_ADC_CDR0_9X5 (0x50) /* Channel Data Register 0 for 9X5 */
|
||||
|
||||
#define AT91_ADC_ACR 0x94 /* Analog Control Register */
|
||||
#define AT91_ADC_ACR_PENDETSENS (0x3 << 0) /* pull-up resistor */
|
||||
|
||||
#define AT91_ADC_TSMR 0xB0
|
||||
#define AT91_ADC_TSMR_TSMODE (3 << 0) /* Touch Screen Mode */
|
||||
#define AT91_ADC_TSMR_TSMODE_NONE (0 << 0)
|
||||
#define AT91_ADC_TSMR_TSMODE_4WIRE_NO_PRESS (1 << 0)
|
||||
#define AT91_ADC_TSMR_TSMODE_4WIRE_PRESS (2 << 0)
|
||||
#define AT91_ADC_TSMR_TSMODE_5WIRE (3 << 0)
|
||||
#define AT91_ADC_TSMR_TSAV (3 << 4) /* Averages samples */
|
||||
#define AT91_ADC_TSMR_TSAV_(x) ((x) << 4)
|
||||
#define AT91_ADC_TSMR_SCTIM (0x0f << 16) /* Switch closure time */
|
||||
#define AT91_ADC_TSMR_PENDBC (0x0f << 28) /* Pen Debounce time */
|
||||
#define AT91_ADC_TSMR_PENDBC_(x) ((x) << 28)
|
||||
#define AT91_ADC_TSMR_NOTSDMA (1 << 22) /* No Touchscreen DMA */
|
||||
#define AT91_ADC_TSMR_PENDET_DIS (0 << 24) /* Pen contact detection disable */
|
||||
#define AT91_ADC_TSMR_PENDET_ENA (1 << 24) /* Pen contact detection enable */
|
||||
|
||||
#define AT91_ADC_TSXPOSR 0xB4
|
||||
#define AT91_ADC_TSYPOSR 0xB8
|
||||
#define AT91_ADC_TSPRESSR 0xBC
|
||||
|
||||
#define AT91_ADC_TRGR_9260 AT91_ADC_MR
|
||||
#define AT91_ADC_TRGR_9G45 0x08
|
||||
#define AT91_ADC_TRGR_9X5 0xC0
|
||||
|
||||
/* Trigger Register bit field */
|
||||
#define AT91_ADC_TRGR_TRGPER (0xffff << 16)
|
||||
#define AT91_ADC_TRGR_TRGPER_(x) ((x) << 16)
|
||||
#define AT91_ADC_TRGR_TRGMOD (0x7 << 0)
|
||||
#define AT91_ADC_TRGR_MOD_PERIOD_TRIG (5 << 0)
|
||||
|
||||
#endif
|
@ -104,5 +104,20 @@
|
||||
/* Clocks */
|
||||
#define AT91_SLOW_CLOCK 32768 /* slow clock */
|
||||
|
||||
/*
|
||||
* FIXME: this is needed to communicate between the pinctrl driver and
|
||||
* the PM implementation in the machine. Possibly part of the PM
|
||||
* implementation should be moved down into the pinctrl driver and get
|
||||
* called as part of the generic suspend/resume path.
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_PINCTRL_AT91
|
||||
extern void at91_pinctrl_gpio_suspend(void);
|
||||
extern void at91_pinctrl_gpio_resume(void);
|
||||
#else
|
||||
static inline void at91_pinctrl_gpio_suspend(void) {}
|
||||
static inline void at91_pinctrl_gpio_resume(void) {}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "at91_aic.h"
|
||||
#include "generic.h"
|
||||
#include "pm.h"
|
||||
#include "gpio.h"
|
||||
|
||||
/*
|
||||
* Show the reason for the previous system reset.
|
||||
|
@ -2,8 +2,8 @@
|
||||
# Makefile for at91 specific clk
|
||||
#
|
||||
|
||||
obj-y += pmc.o
|
||||
obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o
|
||||
obj-y += pmc.o sckc.o
|
||||
obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o
|
||||
obj-y += clk-system.o clk-peripheral.o clk-programmable.o
|
||||
|
||||
obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o
|
||||
|
@ -30,99 +30,412 @@
|
||||
#define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ)
|
||||
#define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT
|
||||
|
||||
struct clk_main {
|
||||
#define MOR_KEY_MASK (0xff << 16)
|
||||
|
||||
struct clk_main_osc {
|
||||
struct clk_hw hw;
|
||||
struct at91_pmc *pmc;
|
||||
unsigned long rate;
|
||||
unsigned int irq;
|
||||
wait_queue_head_t wait;
|
||||
};
|
||||
|
||||
#define to_clk_main(hw) container_of(hw, struct clk_main, hw)
|
||||
#define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
|
||||
|
||||
static irqreturn_t clk_main_irq_handler(int irq, void *dev_id)
|
||||
struct clk_main_rc_osc {
|
||||
struct clk_hw hw;
|
||||
struct at91_pmc *pmc;
|
||||
unsigned int irq;
|
||||
wait_queue_head_t wait;
|
||||
unsigned long frequency;
|
||||
unsigned long accuracy;
|
||||
};
|
||||
|
||||
#define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
|
||||
|
||||
struct clk_rm9200_main {
|
||||
struct clk_hw hw;
|
||||
struct at91_pmc *pmc;
|
||||
};
|
||||
|
||||
#define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
|
||||
|
||||
struct clk_sam9x5_main {
|
||||
struct clk_hw hw;
|
||||
struct at91_pmc *pmc;
|
||||
unsigned int irq;
|
||||
wait_queue_head_t wait;
|
||||
u8 parent;
|
||||
};
|
||||
|
||||
#define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
|
||||
|
||||
static irqreturn_t clk_main_osc_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct clk_main *clkmain = (struct clk_main *)dev_id;
|
||||
struct clk_main_osc *osc = dev_id;
|
||||
|
||||
wake_up(&clkmain->wait);
|
||||
disable_irq_nosync(clkmain->irq);
|
||||
wake_up(&osc->wait);
|
||||
disable_irq_nosync(osc->irq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int clk_main_prepare(struct clk_hw *hw)
|
||||
static int clk_main_osc_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_main *clkmain = to_clk_main(hw);
|
||||
struct at91_pmc *pmc = clkmain->pmc;
|
||||
unsigned long halt_time, timeout;
|
||||
struct clk_main_osc *osc = to_clk_main_osc(hw);
|
||||
struct at91_pmc *pmc = osc->pmc;
|
||||
u32 tmp;
|
||||
|
||||
while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) {
|
||||
enable_irq(clkmain->irq);
|
||||
wait_event(clkmain->wait,
|
||||
pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
|
||||
}
|
||||
|
||||
if (clkmain->rate)
|
||||
tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
|
||||
if (tmp & AT91_PMC_OSCBYPASS)
|
||||
return 0;
|
||||
|
||||
timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
|
||||
do {
|
||||
halt_time = jiffies;
|
||||
tmp = pmc_read(pmc, AT91_CKGR_MCFR);
|
||||
if (tmp & AT91_PMC_MAINRDY)
|
||||
return 0;
|
||||
usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
|
||||
} while (time_before(halt_time, timeout));
|
||||
if (!(tmp & AT91_PMC_MOSCEN)) {
|
||||
tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY;
|
||||
pmc_write(pmc, AT91_CKGR_MOR, tmp);
|
||||
}
|
||||
|
||||
while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) {
|
||||
enable_irq(osc->irq);
|
||||
wait_event(osc->wait,
|
||||
pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_main_is_prepared(struct clk_hw *hw)
|
||||
static void clk_main_osc_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_main *clkmain = to_clk_main(hw);
|
||||
struct clk_main_osc *osc = to_clk_main_osc(hw);
|
||||
struct at91_pmc *pmc = osc->pmc;
|
||||
u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
|
||||
|
||||
return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCS);
|
||||
if (tmp & AT91_PMC_OSCBYPASS)
|
||||
return;
|
||||
|
||||
if (!(tmp & AT91_PMC_MOSCEN))
|
||||
return;
|
||||
|
||||
tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN);
|
||||
pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
|
||||
}
|
||||
|
||||
static unsigned long clk_main_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
static int clk_main_osc_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
u32 tmp;
|
||||
struct clk_main *clkmain = to_clk_main(hw);
|
||||
struct at91_pmc *pmc = clkmain->pmc;
|
||||
struct clk_main_osc *osc = to_clk_main_osc(hw);
|
||||
struct at91_pmc *pmc = osc->pmc;
|
||||
u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
|
||||
|
||||
if (clkmain->rate)
|
||||
return clkmain->rate;
|
||||
if (tmp & AT91_PMC_OSCBYPASS)
|
||||
return 1;
|
||||
|
||||
tmp = pmc_read(pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINF;
|
||||
clkmain->rate = (tmp * parent_rate) / MAINF_DIV;
|
||||
|
||||
return clkmain->rate;
|
||||
return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS) &&
|
||||
(pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN));
|
||||
}
|
||||
|
||||
static const struct clk_ops main_ops = {
|
||||
.prepare = clk_main_prepare,
|
||||
.is_prepared = clk_main_is_prepared,
|
||||
.recalc_rate = clk_main_recalc_rate,
|
||||
static const struct clk_ops main_osc_ops = {
|
||||
.prepare = clk_main_osc_prepare,
|
||||
.unprepare = clk_main_osc_unprepare,
|
||||
.is_prepared = clk_main_osc_is_prepared,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
at91_clk_register_main(struct at91_pmc *pmc,
|
||||
unsigned int irq,
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
unsigned long rate)
|
||||
at91_clk_register_main_osc(struct at91_pmc *pmc,
|
||||
unsigned int irq,
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
bool bypass)
|
||||
{
|
||||
int ret;
|
||||
struct clk_main *clkmain;
|
||||
struct clk_main_osc *osc;
|
||||
struct clk *clk = NULL;
|
||||
struct clk_init_data init;
|
||||
|
||||
if (!pmc || !irq || !name)
|
||||
if (!pmc || !irq || !name || !parent_name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!rate && !parent_name)
|
||||
osc = kzalloc(sizeof(*osc), GFP_KERNEL);
|
||||
if (!osc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &main_osc_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
init.flags = CLK_IGNORE_UNUSED;
|
||||
|
||||
osc->hw.init = &init;
|
||||
osc->pmc = pmc;
|
||||
osc->irq = irq;
|
||||
|
||||
init_waitqueue_head(&osc->wait);
|
||||
irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
|
||||
ret = request_irq(osc->irq, clk_main_osc_irq_handler,
|
||||
IRQF_TRIGGER_HIGH, name, osc);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (bypass)
|
||||
pmc_write(pmc, AT91_CKGR_MOR,
|
||||
(pmc_read(pmc, AT91_CKGR_MOR) &
|
||||
~(MOR_KEY_MASK | AT91_PMC_MOSCEN)) |
|
||||
AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
|
||||
|
||||
clk = clk_register(NULL, &osc->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
free_irq(irq, osc);
|
||||
kfree(osc);
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int irq;
|
||||
const char *name = np->name;
|
||||
const char *parent_name;
|
||||
bool bypass;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
bypass = of_property_read_bool(np, "atmel,osc-bypass");
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (!irq)
|
||||
return;
|
||||
|
||||
clk = at91_clk_register_main_osc(pmc, irq, name, parent_name, bypass);
|
||||
if (IS_ERR(clk))
|
||||
return;
|
||||
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
}
|
||||
|
||||
static irqreturn_t clk_main_rc_osc_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct clk_main_rc_osc *osc = dev_id;
|
||||
|
||||
wake_up(&osc->wait);
|
||||
disable_irq_nosync(osc->irq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int clk_main_rc_osc_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
|
||||
struct at91_pmc *pmc = osc->pmc;
|
||||
u32 tmp;
|
||||
|
||||
tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
|
||||
|
||||
if (!(tmp & AT91_PMC_MOSCRCEN)) {
|
||||
tmp |= AT91_PMC_MOSCRCEN | AT91_PMC_KEY;
|
||||
pmc_write(pmc, AT91_CKGR_MOR, tmp);
|
||||
}
|
||||
|
||||
while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS)) {
|
||||
enable_irq(osc->irq);
|
||||
wait_event(osc->wait,
|
||||
pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
|
||||
struct at91_pmc *pmc = osc->pmc;
|
||||
u32 tmp = pmc_read(pmc, AT91_CKGR_MOR);
|
||||
|
||||
if (!(tmp & AT91_PMC_MOSCRCEN))
|
||||
return;
|
||||
|
||||
tmp &= ~(MOR_KEY_MASK | AT91_PMC_MOSCRCEN);
|
||||
pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
|
||||
}
|
||||
|
||||
static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
|
||||
struct at91_pmc *pmc = osc->pmc;
|
||||
|
||||
return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS) &&
|
||||
(pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCRCEN));
|
||||
}
|
||||
|
||||
static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
|
||||
|
||||
return osc->frequency;
|
||||
}
|
||||
|
||||
static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw,
|
||||
unsigned long parent_acc)
|
||||
{
|
||||
struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
|
||||
|
||||
return osc->accuracy;
|
||||
}
|
||||
|
||||
static const struct clk_ops main_rc_osc_ops = {
|
||||
.prepare = clk_main_rc_osc_prepare,
|
||||
.unprepare = clk_main_rc_osc_unprepare,
|
||||
.is_prepared = clk_main_rc_osc_is_prepared,
|
||||
.recalc_rate = clk_main_rc_osc_recalc_rate,
|
||||
.recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
at91_clk_register_main_rc_osc(struct at91_pmc *pmc,
|
||||
unsigned int irq,
|
||||
const char *name,
|
||||
u32 frequency, u32 accuracy)
|
||||
{
|
||||
int ret;
|
||||
struct clk_main_rc_osc *osc;
|
||||
struct clk *clk = NULL;
|
||||
struct clk_init_data init;
|
||||
|
||||
if (!pmc || !irq || !name || !frequency)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
osc = kzalloc(sizeof(*osc), GFP_KERNEL);
|
||||
if (!osc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &main_rc_osc_ops;
|
||||
init.parent_names = NULL;
|
||||
init.num_parents = 0;
|
||||
init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED;
|
||||
|
||||
osc->hw.init = &init;
|
||||
osc->pmc = pmc;
|
||||
osc->irq = irq;
|
||||
osc->frequency = frequency;
|
||||
osc->accuracy = accuracy;
|
||||
|
||||
init_waitqueue_head(&osc->wait);
|
||||
irq_set_status_flags(osc->irq, IRQ_NOAUTOEN);
|
||||
ret = request_irq(osc->irq, clk_main_rc_osc_irq_handler,
|
||||
IRQF_TRIGGER_HIGH, name, osc);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
clk = clk_register(NULL, &osc->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
free_irq(irq, osc);
|
||||
kfree(osc);
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int irq;
|
||||
u32 frequency = 0;
|
||||
u32 accuracy = 0;
|
||||
const char *name = np->name;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
of_property_read_u32(np, "clock-frequency", &frequency);
|
||||
of_property_read_u32(np, "clock-accuracy", &accuracy);
|
||||
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (!irq)
|
||||
return;
|
||||
|
||||
clk = at91_clk_register_main_rc_osc(pmc, irq, name, frequency,
|
||||
accuracy);
|
||||
if (IS_ERR(clk))
|
||||
return;
|
||||
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
}
|
||||
|
||||
|
||||
static int clk_main_probe_frequency(struct at91_pmc *pmc)
|
||||
{
|
||||
unsigned long prep_time, timeout;
|
||||
u32 tmp;
|
||||
|
||||
timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
|
||||
do {
|
||||
prep_time = jiffies;
|
||||
tmp = pmc_read(pmc, AT91_CKGR_MCFR);
|
||||
if (tmp & AT91_PMC_MAINRDY)
|
||||
return 0;
|
||||
usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
|
||||
} while (time_before(prep_time, timeout));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
if (parent_rate)
|
||||
return parent_rate;
|
||||
|
||||
tmp = pmc_read(pmc, AT91_CKGR_MCFR);
|
||||
if (!(tmp & AT91_PMC_MAINRDY))
|
||||
return 0;
|
||||
|
||||
return ((tmp & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
|
||||
}
|
||||
|
||||
static int clk_rm9200_main_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
|
||||
|
||||
return clk_main_probe_frequency(clkmain->pmc);
|
||||
}
|
||||
|
||||
static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
|
||||
|
||||
return !!(pmc_read(clkmain->pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINRDY);
|
||||
}
|
||||
|
||||
static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
|
||||
|
||||
return clk_main_recalc_rate(clkmain->pmc, parent_rate);
|
||||
}
|
||||
|
||||
static const struct clk_ops rm9200_main_ops = {
|
||||
.prepare = clk_rm9200_main_prepare,
|
||||
.is_prepared = clk_rm9200_main_is_prepared,
|
||||
.recalc_rate = clk_rm9200_main_recalc_rate,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
at91_clk_register_rm9200_main(struct at91_pmc *pmc,
|
||||
const char *name,
|
||||
const char *parent_name)
|
||||
{
|
||||
struct clk_rm9200_main *clkmain;
|
||||
struct clk *clk = NULL;
|
||||
struct clk_init_data init;
|
||||
|
||||
if (!pmc || !name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!parent_name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
|
||||
@ -130,19 +443,154 @@ at91_clk_register_main(struct at91_pmc *pmc,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &main_ops;
|
||||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
init.num_parents = parent_name ? 1 : 0;
|
||||
init.flags = parent_name ? 0 : CLK_IS_ROOT;
|
||||
init.ops = &rm9200_main_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
init.flags = 0;
|
||||
|
||||
clkmain->hw.init = &init;
|
||||
clkmain->pmc = pmc;
|
||||
|
||||
clk = clk_register(NULL, &clkmain->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(clkmain);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void __init of_at91rm9200_clk_main_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc)
|
||||
{
|
||||
struct clk *clk;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
clk = at91_clk_register_rm9200_main(pmc, name, parent_name);
|
||||
if (IS_ERR(clk))
|
||||
return;
|
||||
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
}
|
||||
|
||||
static irqreturn_t clk_sam9x5_main_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct clk_sam9x5_main *clkmain = dev_id;
|
||||
|
||||
wake_up(&clkmain->wait);
|
||||
disable_irq_nosync(clkmain->irq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int clk_sam9x5_main_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
|
||||
struct at91_pmc *pmc = clkmain->pmc;
|
||||
|
||||
while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
|
||||
enable_irq(clkmain->irq);
|
||||
wait_event(clkmain->wait,
|
||||
pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
|
||||
}
|
||||
|
||||
return clk_main_probe_frequency(pmc);
|
||||
}
|
||||
|
||||
static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
|
||||
|
||||
return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
|
||||
}
|
||||
|
||||
static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
|
||||
|
||||
return clk_main_recalc_rate(clkmain->pmc, parent_rate);
|
||||
}
|
||||
|
||||
static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
|
||||
struct at91_pmc *pmc = clkmain->pmc;
|
||||
u32 tmp;
|
||||
|
||||
if (index > 1)
|
||||
return -EINVAL;
|
||||
|
||||
tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK;
|
||||
|
||||
if (index && !(tmp & AT91_PMC_MOSCSEL))
|
||||
pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
|
||||
else if (!index && (tmp & AT91_PMC_MOSCSEL))
|
||||
pmc_write(pmc, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
|
||||
|
||||
while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) {
|
||||
enable_irq(clkmain->irq);
|
||||
wait_event(clkmain->wait,
|
||||
pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
|
||||
|
||||
return !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN);
|
||||
}
|
||||
|
||||
static const struct clk_ops sam9x5_main_ops = {
|
||||
.prepare = clk_sam9x5_main_prepare,
|
||||
.is_prepared = clk_sam9x5_main_is_prepared,
|
||||
.recalc_rate = clk_sam9x5_main_recalc_rate,
|
||||
.set_parent = clk_sam9x5_main_set_parent,
|
||||
.get_parent = clk_sam9x5_main_get_parent,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
at91_clk_register_sam9x5_main(struct at91_pmc *pmc,
|
||||
unsigned int irq,
|
||||
const char *name,
|
||||
const char **parent_names,
|
||||
int num_parents)
|
||||
{
|
||||
int ret;
|
||||
struct clk_sam9x5_main *clkmain;
|
||||
struct clk *clk = NULL;
|
||||
struct clk_init_data init;
|
||||
|
||||
if (!pmc || !irq || !name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!parent_names || !num_parents)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
|
||||
if (!clkmain)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &sam9x5_main_ops;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
init.flags = CLK_SET_PARENT_GATE;
|
||||
|
||||
clkmain->hw.init = &init;
|
||||
clkmain->rate = rate;
|
||||
clkmain->pmc = pmc;
|
||||
clkmain->irq = irq;
|
||||
clkmain->parent = !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) &
|
||||
AT91_PMC_MOSCEN);
|
||||
init_waitqueue_head(&clkmain->wait);
|
||||
irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN);
|
||||
ret = request_irq(clkmain->irq, clk_main_irq_handler,
|
||||
IRQF_TRIGGER_HIGH, "clk-main", clkmain);
|
||||
ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler,
|
||||
IRQF_TRIGGER_HIGH, name, clkmain);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@ -155,33 +603,36 @@ at91_clk_register_main(struct at91_pmc *pmc,
|
||||
return clk;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void __init
|
||||
of_at91_clk_main_setup(struct device_node *np, struct at91_pmc *pmc)
|
||||
void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc)
|
||||
{
|
||||
struct clk *clk;
|
||||
const char *parent_names[2];
|
||||
int num_parents;
|
||||
unsigned int irq;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
u32 rate = 0;
|
||||
int i;
|
||||
|
||||
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
|
||||
if (num_parents <= 0 || num_parents > 2)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_parents; ++i) {
|
||||
parent_names[i] = of_clk_get_parent_name(np, i);
|
||||
if (!parent_names[i])
|
||||
return;
|
||||
}
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
of_property_read_u32(np, "clock-frequency", &rate);
|
||||
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (!irq)
|
||||
return;
|
||||
|
||||
clk = at91_clk_register_main(pmc, irq, name, parent_name, rate);
|
||||
clk = at91_clk_register_sam9x5_main(pmc, irq, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(clk))
|
||||
return;
|
||||
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
}
|
||||
|
||||
void __init of_at91rm9200_clk_main_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc)
|
||||
{
|
||||
of_at91_clk_main_setup(np, pmc);
|
||||
}
|
||||
|
467
drivers/clk/at91/clk-slow.c
Normal file
467
drivers/clk/at91/clk-slow.c
Normal file
@ -0,0 +1,467 @@
|
||||
/*
|
||||
* drivers/clk/at91/clk-slow.c
|
||||
*
|
||||
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk/at91_pmc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include "pmc.h"
|
||||
#include "sckc.h"
|
||||
|
||||
#define SLOW_CLOCK_FREQ 32768
|
||||
#define SLOWCK_SW_CYCLES 5
|
||||
#define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
|
||||
SLOW_CLOCK_FREQ)
|
||||
|
||||
#define AT91_SCKC_CR 0x00
|
||||
#define AT91_SCKC_RCEN (1 << 0)
|
||||
#define AT91_SCKC_OSC32EN (1 << 1)
|
||||
#define AT91_SCKC_OSC32BYP (1 << 2)
|
||||
#define AT91_SCKC_OSCSEL (1 << 3)
|
||||
|
||||
struct clk_slow_osc {
|
||||
struct clk_hw hw;
|
||||
void __iomem *sckcr;
|
||||
unsigned long startup_usec;
|
||||
};
|
||||
|
||||
#define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
|
||||
|
||||
struct clk_slow_rc_osc {
|
||||
struct clk_hw hw;
|
||||
void __iomem *sckcr;
|
||||
unsigned long frequency;
|
||||
unsigned long accuracy;
|
||||
unsigned long startup_usec;
|
||||
};
|
||||
|
||||
#define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
|
||||
|
||||
struct clk_sam9260_slow {
|
||||
struct clk_hw hw;
|
||||
struct at91_pmc *pmc;
|
||||
};
|
||||
|
||||
#define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
|
||||
|
||||
struct clk_sam9x5_slow {
|
||||
struct clk_hw hw;
|
||||
void __iomem *sckcr;
|
||||
u8 parent;
|
||||
};
|
||||
|
||||
#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
|
||||
|
||||
|
||||
static int clk_slow_osc_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_slow_osc *osc = to_clk_slow_osc(hw);
|
||||
void __iomem *sckcr = osc->sckcr;
|
||||
u32 tmp = readl(sckcr);
|
||||
|
||||
if (tmp & AT91_SCKC_OSC32BYP)
|
||||
return 0;
|
||||
|
||||
writel(tmp | AT91_SCKC_OSC32EN, sckcr);
|
||||
|
||||
usleep_range(osc->startup_usec, osc->startup_usec + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clk_slow_osc_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_slow_osc *osc = to_clk_slow_osc(hw);
|
||||
void __iomem *sckcr = osc->sckcr;
|
||||
u32 tmp = readl(sckcr);
|
||||
|
||||
if (tmp & AT91_SCKC_OSC32BYP)
|
||||
return;
|
||||
|
||||
writel(tmp & ~AT91_SCKC_OSC32EN, sckcr);
|
||||
}
|
||||
|
||||
static int clk_slow_osc_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_slow_osc *osc = to_clk_slow_osc(hw);
|
||||
void __iomem *sckcr = osc->sckcr;
|
||||
u32 tmp = readl(sckcr);
|
||||
|
||||
if (tmp & AT91_SCKC_OSC32BYP)
|
||||
return 1;
|
||||
|
||||
return !!(tmp & AT91_SCKC_OSC32EN);
|
||||
}
|
||||
|
||||
static const struct clk_ops slow_osc_ops = {
|
||||
.prepare = clk_slow_osc_prepare,
|
||||
.unprepare = clk_slow_osc_unprepare,
|
||||
.is_prepared = clk_slow_osc_is_prepared,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
at91_clk_register_slow_osc(void __iomem *sckcr,
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
unsigned long startup,
|
||||
bool bypass)
|
||||
{
|
||||
struct clk_slow_osc *osc;
|
||||
struct clk *clk = NULL;
|
||||
struct clk_init_data init;
|
||||
|
||||
if (!sckcr || !name || !parent_name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
osc = kzalloc(sizeof(*osc), GFP_KERNEL);
|
||||
if (!osc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &slow_osc_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
init.flags = CLK_IGNORE_UNUSED;
|
||||
|
||||
osc->hw.init = &init;
|
||||
osc->sckcr = sckcr;
|
||||
osc->startup_usec = startup;
|
||||
|
||||
if (bypass)
|
||||
writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP,
|
||||
sckcr);
|
||||
|
||||
clk = clk_register(NULL, &osc->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(osc);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np,
|
||||
void __iomem *sckcr)
|
||||
{
|
||||
struct clk *clk;
|
||||
const char *parent_name;
|
||||
const char *name = np->name;
|
||||
u32 startup;
|
||||
bool bypass;
|
||||
|
||||
parent_name = of_clk_get_parent_name(np, 0);
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
of_property_read_u32(np, "atmel,startup-time-usec", &startup);
|
||||
bypass = of_property_read_bool(np, "atmel,osc-bypass");
|
||||
|
||||
clk = at91_clk_register_slow_osc(sckcr, name, parent_name, startup,
|
||||
bypass);
|
||||
if (IS_ERR(clk))
|
||||
return;
|
||||
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
}
|
||||
|
||||
static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
|
||||
|
||||
return osc->frequency;
|
||||
}
|
||||
|
||||
static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw,
|
||||
unsigned long parent_acc)
|
||||
{
|
||||
struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
|
||||
|
||||
return osc->accuracy;
|
||||
}
|
||||
|
||||
static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
|
||||
void __iomem *sckcr = osc->sckcr;
|
||||
|
||||
writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr);
|
||||
|
||||
usleep_range(osc->startup_usec, osc->startup_usec + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clk_slow_rc_osc_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
|
||||
void __iomem *sckcr = osc->sckcr;
|
||||
|
||||
writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr);
|
||||
}
|
||||
|
||||
static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
|
||||
|
||||
return !!(readl(osc->sckcr) & AT91_SCKC_RCEN);
|
||||
}
|
||||
|
||||
static const struct clk_ops slow_rc_osc_ops = {
|
||||
.prepare = clk_slow_rc_osc_prepare,
|
||||
.unprepare = clk_slow_rc_osc_unprepare,
|
||||
.is_prepared = clk_slow_rc_osc_is_prepared,
|
||||
.recalc_rate = clk_slow_rc_osc_recalc_rate,
|
||||
.recalc_accuracy = clk_slow_rc_osc_recalc_accuracy,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
at91_clk_register_slow_rc_osc(void __iomem *sckcr,
|
||||
const char *name,
|
||||
unsigned long frequency,
|
||||
unsigned long accuracy,
|
||||
unsigned long startup)
|
||||
{
|
||||
struct clk_slow_rc_osc *osc;
|
||||
struct clk *clk = NULL;
|
||||
struct clk_init_data init;
|
||||
|
||||
if (!sckcr || !name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
osc = kzalloc(sizeof(*osc), GFP_KERNEL);
|
||||
if (!osc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &slow_rc_osc_ops;
|
||||
init.parent_names = NULL;
|
||||
init.num_parents = 0;
|
||||
init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED;
|
||||
|
||||
osc->hw.init = &init;
|
||||
osc->sckcr = sckcr;
|
||||
osc->frequency = frequency;
|
||||
osc->accuracy = accuracy;
|
||||
osc->startup_usec = startup;
|
||||
|
||||
clk = clk_register(NULL, &osc->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(osc);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np,
|
||||
void __iomem *sckcr)
|
||||
{
|
||||
struct clk *clk;
|
||||
u32 frequency = 0;
|
||||
u32 accuracy = 0;
|
||||
u32 startup = 0;
|
||||
const char *name = np->name;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
of_property_read_u32(np, "clock-frequency", &frequency);
|
||||
of_property_read_u32(np, "clock-accuracy", &accuracy);
|
||||
of_property_read_u32(np, "atmel,startup-time-usec", &startup);
|
||||
|
||||
clk = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy,
|
||||
startup);
|
||||
if (IS_ERR(clk))
|
||||
return;
|
||||
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
}
|
||||
|
||||
static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
|
||||
void __iomem *sckcr = slowck->sckcr;
|
||||
u32 tmp;
|
||||
|
||||
if (index > 1)
|
||||
return -EINVAL;
|
||||
|
||||
tmp = readl(sckcr);
|
||||
|
||||
if ((!index && !(tmp & AT91_SCKC_OSCSEL)) ||
|
||||
(index && (tmp & AT91_SCKC_OSCSEL)))
|
||||
return 0;
|
||||
|
||||
if (index)
|
||||
tmp |= AT91_SCKC_OSCSEL;
|
||||
else
|
||||
tmp &= ~AT91_SCKC_OSCSEL;
|
||||
|
||||
writel(tmp, sckcr);
|
||||
|
||||
usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
|
||||
|
||||
return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL);
|
||||
}
|
||||
|
||||
static const struct clk_ops sam9x5_slow_ops = {
|
||||
.set_parent = clk_sam9x5_slow_set_parent,
|
||||
.get_parent = clk_sam9x5_slow_get_parent,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
at91_clk_register_sam9x5_slow(void __iomem *sckcr,
|
||||
const char *name,
|
||||
const char **parent_names,
|
||||
int num_parents)
|
||||
{
|
||||
struct clk_sam9x5_slow *slowck;
|
||||
struct clk *clk = NULL;
|
||||
struct clk_init_data init;
|
||||
|
||||
if (!sckcr || !name || !parent_names || !num_parents)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
|
||||
if (!slowck)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &sam9x5_slow_ops;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
init.flags = 0;
|
||||
|
||||
slowck->hw.init = &init;
|
||||
slowck->sckcr = sckcr;
|
||||
slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL);
|
||||
|
||||
clk = clk_register(NULL, &slowck->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(slowck);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
|
||||
void __iomem *sckcr)
|
||||
{
|
||||
struct clk *clk;
|
||||
const char *parent_names[2];
|
||||
int num_parents;
|
||||
const char *name = np->name;
|
||||
int i;
|
||||
|
||||
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
|
||||
if (num_parents <= 0 || num_parents > 2)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_parents; ++i) {
|
||||
parent_names[i] = of_clk_get_parent_name(np, i);
|
||||
if (!parent_names[i])
|
||||
return;
|
||||
}
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
clk = at91_clk_register_sam9x5_slow(sckcr, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(clk))
|
||||
return;
|
||||
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
}
|
||||
|
||||
static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw);
|
||||
|
||||
return !!(pmc_read(slowck->pmc, AT91_PMC_SR) & AT91_PMC_OSCSEL);
|
||||
}
|
||||
|
||||
static const struct clk_ops sam9260_slow_ops = {
|
||||
.get_parent = clk_sam9260_slow_get_parent,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
at91_clk_register_sam9260_slow(struct at91_pmc *pmc,
|
||||
const char *name,
|
||||
const char **parent_names,
|
||||
int num_parents)
|
||||
{
|
||||
struct clk_sam9260_slow *slowck;
|
||||
struct clk *clk = NULL;
|
||||
struct clk_init_data init;
|
||||
|
||||
if (!pmc || !name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!parent_names || !num_parents)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
|
||||
if (!slowck)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &sam9260_slow_ops;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = num_parents;
|
||||
init.flags = 0;
|
||||
|
||||
slowck->hw.init = &init;
|
||||
slowck->pmc = pmc;
|
||||
|
||||
clk = clk_register(NULL, &slowck->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(slowck);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc)
|
||||
{
|
||||
struct clk *clk;
|
||||
const char *parent_names[2];
|
||||
int num_parents;
|
||||
const char *name = np->name;
|
||||
int i;
|
||||
|
||||
num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
|
||||
if (num_parents <= 0 || num_parents > 1)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_parents; ++i) {
|
||||
parent_names[i] = of_clk_get_parent_name(np, i);
|
||||
if (!parent_names[i])
|
||||
return;
|
||||
}
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
clk = at91_clk_register_sam9260_slow(pmc, name, parent_names,
|
||||
num_parents);
|
||||
if (IS_ERR(clk))
|
||||
return;
|
||||
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
}
|
@ -229,11 +229,28 @@ out_free_pmc:
|
||||
}
|
||||
|
||||
static const struct of_device_id pmc_clk_ids[] __initconst = {
|
||||
/* Slow oscillator */
|
||||
{
|
||||
.compatible = "atmel,at91sam9260-clk-slow",
|
||||
.data = of_at91sam9260_clk_slow_setup,
|
||||
},
|
||||
/* Main clock */
|
||||
{
|
||||
.compatible = "atmel,at91rm9200-clk-main-osc",
|
||||
.data = of_at91rm9200_clk_main_osc_setup,
|
||||
},
|
||||
{
|
||||
.compatible = "atmel,at91sam9x5-clk-main-rc-osc",
|
||||
.data = of_at91sam9x5_clk_main_rc_osc_setup,
|
||||
},
|
||||
{
|
||||
.compatible = "atmel,at91rm9200-clk-main",
|
||||
.data = of_at91rm9200_clk_main_setup,
|
||||
},
|
||||
{
|
||||
.compatible = "atmel,at91sam9x5-clk-main",
|
||||
.data = of_at91sam9x5_clk_main_setup,
|
||||
},
|
||||
/* PLL clocks */
|
||||
{
|
||||
.compatible = "atmel,at91rm9200-clk-pll",
|
||||
|
@ -58,8 +58,17 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value)
|
||||
int of_at91_get_clk_range(struct device_node *np, const char *propname,
|
||||
struct clk_range *range);
|
||||
|
||||
extern void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc);
|
||||
|
||||
extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc);
|
||||
extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc);
|
||||
extern void __init of_at91rm9200_clk_main_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc);
|
||||
extern void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc);
|
||||
|
||||
extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np,
|
||||
struct at91_pmc *pmc);
|
||||
|
57
drivers/clk/at91/sckc.c
Normal file
57
drivers/clk/at91/sckc.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* drivers/clk/at91/sckc.c
|
||||
*
|
||||
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "sckc.h"
|
||||
|
||||
static const struct of_device_id sckc_clk_ids[] __initconst = {
|
||||
/* Slow clock */
|
||||
{
|
||||
.compatible = "atmel,at91sam9x5-clk-slow-osc",
|
||||
.data = of_at91sam9x5_clk_slow_osc_setup,
|
||||
},
|
||||
{
|
||||
.compatible = "atmel,at91sam9x5-clk-slow-rc-osc",
|
||||
.data = of_at91sam9x5_clk_slow_rc_osc_setup,
|
||||
},
|
||||
{
|
||||
.compatible = "atmel,at91sam9x5-clk-slow",
|
||||
.data = of_at91sam9x5_clk_slow_setup,
|
||||
},
|
||||
{ /*sentinel*/ }
|
||||
};
|
||||
|
||||
static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
|
||||
{
|
||||
struct device_node *childnp;
|
||||
void (*clk_setup)(struct device_node *, void __iomem *);
|
||||
const struct of_device_id *clk_id;
|
||||
void __iomem *regbase = of_iomap(np, 0);
|
||||
|
||||
if (!regbase)
|
||||
return;
|
||||
|
||||
for_each_child_of_node(np, childnp) {
|
||||
clk_id = of_match_node(sckc_clk_ids, childnp);
|
||||
if (!clk_id)
|
||||
continue;
|
||||
clk_setup = clk_id->data;
|
||||
clk_setup(childnp, regbase);
|
||||
}
|
||||
}
|
||||
CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
|
||||
of_at91sam9x5_sckc_setup);
|
22
drivers/clk/at91/sckc.h
Normal file
22
drivers/clk/at91/sckc.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* drivers/clk/at91/sckc.h
|
||||
*
|
||||
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.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.
|
||||
*/
|
||||
|
||||
#ifndef __AT91_SCKC_H_
|
||||
#define __AT91_SCKC_H_
|
||||
|
||||
extern void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np,
|
||||
void __iomem *sckcr);
|
||||
extern void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np,
|
||||
void __iomem *sckcr);
|
||||
extern void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
|
||||
void __iomem *sckcr);
|
||||
|
||||
#endif /* __AT91_SCKC_H_ */
|
@ -31,7 +31,108 @@
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
|
||||
#include <mach/at91_adc.h>
|
||||
/* Registers */
|
||||
#define AT91_ADC_CR 0x00 /* Control Register */
|
||||
#define AT91_ADC_SWRST (1 << 0) /* Software Reset */
|
||||
#define AT91_ADC_START (1 << 1) /* Start Conversion */
|
||||
|
||||
#define AT91_ADC_MR 0x04 /* Mode Register */
|
||||
#define AT91_ADC_TSAMOD (3 << 0) /* ADC mode */
|
||||
#define AT91_ADC_TSAMOD_ADC_ONLY_MODE (0 << 0) /* ADC Mode */
|
||||
#define AT91_ADC_TSAMOD_TS_ONLY_MODE (1 << 0) /* Touch Screen Only Mode */
|
||||
#define AT91_ADC_TRGEN (1 << 0) /* Trigger Enable */
|
||||
#define AT91_ADC_TRGSEL (7 << 1) /* Trigger Selection */
|
||||
#define AT91_ADC_TRGSEL_TC0 (0 << 1)
|
||||
#define AT91_ADC_TRGSEL_TC1 (1 << 1)
|
||||
#define AT91_ADC_TRGSEL_TC2 (2 << 1)
|
||||
#define AT91_ADC_TRGSEL_EXTERNAL (6 << 1)
|
||||
#define AT91_ADC_LOWRES (1 << 4) /* Low Resolution */
|
||||
#define AT91_ADC_SLEEP (1 << 5) /* Sleep Mode */
|
||||
#define AT91_ADC_PENDET (1 << 6) /* Pen contact detection enable */
|
||||
#define AT91_ADC_PRESCAL_9260 (0x3f << 8) /* Prescalar Rate Selection */
|
||||
#define AT91_ADC_PRESCAL_9G45 (0xff << 8)
|
||||
#define AT91_ADC_PRESCAL_(x) ((x) << 8)
|
||||
#define AT91_ADC_STARTUP_9260 (0x1f << 16) /* Startup Up Time */
|
||||
#define AT91_ADC_STARTUP_9G45 (0x7f << 16)
|
||||
#define AT91_ADC_STARTUP_9X5 (0xf << 16)
|
||||
#define AT91_ADC_STARTUP_(x) ((x) << 16)
|
||||
#define AT91_ADC_SHTIM (0xf << 24) /* Sample & Hold Time */
|
||||
#define AT91_ADC_SHTIM_(x) ((x) << 24)
|
||||
#define AT91_ADC_PENDBC (0x0f << 28) /* Pen Debounce time */
|
||||
#define AT91_ADC_PENDBC_(x) ((x) << 28)
|
||||
|
||||
#define AT91_ADC_TSR 0x0C
|
||||
#define AT91_ADC_TSR_SHTIM (0xf << 24) /* Sample & Hold Time */
|
||||
#define AT91_ADC_TSR_SHTIM_(x) ((x) << 24)
|
||||
|
||||
#define AT91_ADC_CHER 0x10 /* Channel Enable Register */
|
||||
#define AT91_ADC_CHDR 0x14 /* Channel Disable Register */
|
||||
#define AT91_ADC_CHSR 0x18 /* Channel Status Register */
|
||||
#define AT91_ADC_CH(n) (1 << (n)) /* Channel Number */
|
||||
|
||||
#define AT91_ADC_SR 0x1C /* Status Register */
|
||||
#define AT91_ADC_EOC(n) (1 << (n)) /* End of Conversion on Channel N */
|
||||
#define AT91_ADC_OVRE(n) (1 << ((n) + 8))/* Overrun Error on Channel N */
|
||||
#define AT91_ADC_DRDY (1 << 16) /* Data Ready */
|
||||
#define AT91_ADC_GOVRE (1 << 17) /* General Overrun Error */
|
||||
#define AT91_ADC_ENDRX (1 << 18) /* End of RX Buffer */
|
||||
#define AT91_ADC_RXFUFF (1 << 19) /* RX Buffer Full */
|
||||
|
||||
#define AT91_ADC_SR_9X5 0x30 /* Status Register for 9x5 */
|
||||
#define AT91_ADC_SR_DRDY_9X5 (1 << 24) /* Data Ready */
|
||||
|
||||
#define AT91_ADC_LCDR 0x20 /* Last Converted Data Register */
|
||||
#define AT91_ADC_LDATA (0x3ff)
|
||||
|
||||
#define AT91_ADC_IER 0x24 /* Interrupt Enable Register */
|
||||
#define AT91_ADC_IDR 0x28 /* Interrupt Disable Register */
|
||||
#define AT91_ADC_IMR 0x2C /* Interrupt Mask Register */
|
||||
#define AT91RL_ADC_IER_PEN (1 << 20)
|
||||
#define AT91RL_ADC_IER_NOPEN (1 << 21)
|
||||
#define AT91_ADC_IER_PEN (1 << 29)
|
||||
#define AT91_ADC_IER_NOPEN (1 << 30)
|
||||
#define AT91_ADC_IER_XRDY (1 << 20)
|
||||
#define AT91_ADC_IER_YRDY (1 << 21)
|
||||
#define AT91_ADC_IER_PRDY (1 << 22)
|
||||
#define AT91_ADC_ISR_PENS (1 << 31)
|
||||
|
||||
#define AT91_ADC_CHR(n) (0x30 + ((n) * 4)) /* Channel Data Register N */
|
||||
#define AT91_ADC_DATA (0x3ff)
|
||||
|
||||
#define AT91_ADC_CDR0_9X5 (0x50) /* Channel Data Register 0 for 9X5 */
|
||||
|
||||
#define AT91_ADC_ACR 0x94 /* Analog Control Register */
|
||||
#define AT91_ADC_ACR_PENDETSENS (0x3 << 0) /* pull-up resistor */
|
||||
|
||||
#define AT91_ADC_TSMR 0xB0
|
||||
#define AT91_ADC_TSMR_TSMODE (3 << 0) /* Touch Screen Mode */
|
||||
#define AT91_ADC_TSMR_TSMODE_NONE (0 << 0)
|
||||
#define AT91_ADC_TSMR_TSMODE_4WIRE_NO_PRESS (1 << 0)
|
||||
#define AT91_ADC_TSMR_TSMODE_4WIRE_PRESS (2 << 0)
|
||||
#define AT91_ADC_TSMR_TSMODE_5WIRE (3 << 0)
|
||||
#define AT91_ADC_TSMR_TSAV (3 << 4) /* Averages samples */
|
||||
#define AT91_ADC_TSMR_TSAV_(x) ((x) << 4)
|
||||
#define AT91_ADC_TSMR_SCTIM (0x0f << 16) /* Switch closure time */
|
||||
#define AT91_ADC_TSMR_PENDBC (0x0f << 28) /* Pen Debounce time */
|
||||
#define AT91_ADC_TSMR_PENDBC_(x) ((x) << 28)
|
||||
#define AT91_ADC_TSMR_NOTSDMA (1 << 22) /* No Touchscreen DMA */
|
||||
#define AT91_ADC_TSMR_PENDET_DIS (0 << 24) /* Pen contact detection disable */
|
||||
#define AT91_ADC_TSMR_PENDET_ENA (1 << 24) /* Pen contact detection enable */
|
||||
|
||||
#define AT91_ADC_TSXPOSR 0xB4
|
||||
#define AT91_ADC_TSYPOSR 0xB8
|
||||
#define AT91_ADC_TSPRESSR 0xBC
|
||||
|
||||
#define AT91_ADC_TRGR_9260 AT91_ADC_MR
|
||||
#define AT91_ADC_TRGR_9G45 0x08
|
||||
#define AT91_ADC_TRGR_9X5 0xC0
|
||||
|
||||
/* Trigger Register bit field */
|
||||
#define AT91_ADC_TRGR_TRGPER (0xffff << 16)
|
||||
#define AT91_ADC_TRGR_TRGPER_(x) ((x) << 16)
|
||||
#define AT91_ADC_TRGR_TRGMOD (0x7 << 0)
|
||||
#define AT91_ADC_TRGR_NONE (0 << 0)
|
||||
#define AT91_ADC_TRGR_MOD_PERIOD_TRIG (5 << 0)
|
||||
|
||||
#define AT91_ADC_CHAN(st, ch) \
|
||||
(st->registers->channel_base + (ch * 4))
|
||||
@ -46,6 +147,29 @@
|
||||
#define TOUCH_SAMPLE_PERIOD_US 2000 /* 2ms */
|
||||
#define TOUCH_PEN_DETECT_DEBOUNCE_US 200
|
||||
|
||||
#define MAX_RLPOS_BITS 10
|
||||
#define TOUCH_SAMPLE_PERIOD_US_RL 10000 /* 10ms, the SoC can't keep up with 2ms */
|
||||
#define TOUCH_SHTIM 0xa
|
||||
|
||||
/**
|
||||
* struct at91_adc_reg_desc - Various informations relative to registers
|
||||
* @channel_base: Base offset for the channel data registers
|
||||
* @drdy_mask: Mask of the DRDY field in the relevant registers
|
||||
(Interruptions registers mostly)
|
||||
* @status_register: Offset of the Interrupt Status Register
|
||||
* @trigger_register: Offset of the Trigger setup register
|
||||
* @mr_prescal_mask: Mask of the PRESCAL field in the adc MR register
|
||||
* @mr_startup_mask: Mask of the STARTUP field in the adc MR register
|
||||
*/
|
||||
struct at91_adc_reg_desc {
|
||||
u8 channel_base;
|
||||
u32 drdy_mask;
|
||||
u8 status_register;
|
||||
u8 trigger_register;
|
||||
u32 mr_prescal_mask;
|
||||
u32 mr_startup_mask;
|
||||
};
|
||||
|
||||
struct at91_adc_caps {
|
||||
bool has_ts; /* Support touch screen */
|
||||
bool has_tsmr; /* only at91sam9x5, sama5d3 have TSMR reg */
|
||||
@ -64,12 +188,6 @@ struct at91_adc_caps {
|
||||
struct at91_adc_reg_desc registers;
|
||||
};
|
||||
|
||||
enum atmel_adc_ts_type {
|
||||
ATMEL_ADC_TOUCHSCREEN_NONE = 0,
|
||||
ATMEL_ADC_TOUCHSCREEN_4WIRE = 4,
|
||||
ATMEL_ADC_TOUCHSCREEN_5WIRE = 5,
|
||||
};
|
||||
|
||||
struct at91_adc_state {
|
||||
struct clk *adc_clk;
|
||||
u16 *buffer;
|
||||
@ -114,6 +232,11 @@ struct at91_adc_state {
|
||||
|
||||
u16 ts_sample_period_val;
|
||||
u32 ts_pressure_threshold;
|
||||
u16 ts_pendbc;
|
||||
|
||||
bool ts_bufferedmeasure;
|
||||
u32 ts_prev_absx;
|
||||
u32 ts_prev_absy;
|
||||
};
|
||||
|
||||
static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
|
||||
@ -220,7 +343,72 @@ static int at91_ts_sample(struct at91_adc_state *st)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t at91_adc_interrupt(int irq, void *private)
|
||||
static irqreturn_t at91_adc_rl_interrupt(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *idev = private;
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
u32 status = at91_adc_readl(st, st->registers->status_register);
|
||||
unsigned int reg;
|
||||
|
||||
status &= at91_adc_readl(st, AT91_ADC_IMR);
|
||||
if (status & st->registers->drdy_mask)
|
||||
handle_adc_eoc_trigger(irq, idev);
|
||||
|
||||
if (status & AT91RL_ADC_IER_PEN) {
|
||||
/* Disabling pen debounce is required to get a NOPEN irq */
|
||||
reg = at91_adc_readl(st, AT91_ADC_MR);
|
||||
reg &= ~AT91_ADC_PENDBC;
|
||||
at91_adc_writel(st, AT91_ADC_MR, reg);
|
||||
|
||||
at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_PEN);
|
||||
at91_adc_writel(st, AT91_ADC_IER, AT91RL_ADC_IER_NOPEN
|
||||
| AT91_ADC_EOC(3));
|
||||
/* Set up period trigger for sampling */
|
||||
at91_adc_writel(st, st->registers->trigger_register,
|
||||
AT91_ADC_TRGR_MOD_PERIOD_TRIG |
|
||||
AT91_ADC_TRGR_TRGPER_(st->ts_sample_period_val));
|
||||
} else if (status & AT91RL_ADC_IER_NOPEN) {
|
||||
reg = at91_adc_readl(st, AT91_ADC_MR);
|
||||
reg |= AT91_ADC_PENDBC_(st->ts_pendbc) & AT91_ADC_PENDBC;
|
||||
at91_adc_writel(st, AT91_ADC_MR, reg);
|
||||
at91_adc_writel(st, st->registers->trigger_register,
|
||||
AT91_ADC_TRGR_NONE);
|
||||
|
||||
at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_NOPEN
|
||||
| AT91_ADC_EOC(3));
|
||||
at91_adc_writel(st, AT91_ADC_IER, AT91RL_ADC_IER_PEN);
|
||||
st->ts_bufferedmeasure = false;
|
||||
input_report_key(st->ts_input, BTN_TOUCH, 0);
|
||||
input_sync(st->ts_input);
|
||||
} else if (status & AT91_ADC_EOC(3)) {
|
||||
/* Conversion finished */
|
||||
if (st->ts_bufferedmeasure) {
|
||||
/*
|
||||
* Last measurement is always discarded, since it can
|
||||
* be erroneous.
|
||||
* Always report previous measurement
|
||||
*/
|
||||
input_report_abs(st->ts_input, ABS_X, st->ts_prev_absx);
|
||||
input_report_abs(st->ts_input, ABS_Y, st->ts_prev_absy);
|
||||
input_report_key(st->ts_input, BTN_TOUCH, 1);
|
||||
input_sync(st->ts_input);
|
||||
} else
|
||||
st->ts_bufferedmeasure = true;
|
||||
|
||||
/* Now make new measurement */
|
||||
st->ts_prev_absx = at91_adc_readl(st, AT91_ADC_CHAN(st, 3))
|
||||
<< MAX_RLPOS_BITS;
|
||||
st->ts_prev_absx /= at91_adc_readl(st, AT91_ADC_CHAN(st, 2));
|
||||
|
||||
st->ts_prev_absy = at91_adc_readl(st, AT91_ADC_CHAN(st, 1))
|
||||
<< MAX_RLPOS_BITS;
|
||||
st->ts_prev_absy /= at91_adc_readl(st, AT91_ADC_CHAN(st, 0));
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t at91_adc_9x5_interrupt(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *idev = private;
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
@ -653,6 +841,8 @@ static int at91_adc_probe_dt_ts(struct device_node *node,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!st->caps->has_tsmr)
|
||||
return 0;
|
||||
prop = 0;
|
||||
of_property_read_u32(node, "atmel,adc-ts-pressure-threshold", &prop);
|
||||
st->ts_pressure_threshold = prop;
|
||||
@ -776,6 +966,7 @@ static int at91_adc_probe_pdata(struct at91_adc_state *st,
|
||||
st->trigger_number = pdata->trigger_number;
|
||||
st->trigger_list = pdata->trigger_list;
|
||||
st->registers = &st->caps->registers;
|
||||
st->touchscreen_type = pdata->touchscreen_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -790,7 +981,10 @@ static int atmel_ts_open(struct input_dev *dev)
|
||||
{
|
||||
struct at91_adc_state *st = input_get_drvdata(dev);
|
||||
|
||||
at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN);
|
||||
if (st->caps->has_tsmr)
|
||||
at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN);
|
||||
else
|
||||
at91_adc_writel(st, AT91_ADC_IER, AT91RL_ADC_IER_PEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -798,44 +992,60 @@ static void atmel_ts_close(struct input_dev *dev)
|
||||
{
|
||||
struct at91_adc_state *st = input_get_drvdata(dev);
|
||||
|
||||
at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN);
|
||||
if (st->caps->has_tsmr)
|
||||
at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN);
|
||||
else
|
||||
at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_PEN);
|
||||
}
|
||||
|
||||
static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
|
||||
{
|
||||
u32 reg = 0, pendbc;
|
||||
u32 reg = 0;
|
||||
int i = 0;
|
||||
|
||||
/* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid
|
||||
* pen detect noise.
|
||||
* The formula is : Pen Detect Debounce Time = (2 ^ pendbc) / ADCClock
|
||||
*/
|
||||
st->ts_pendbc = round_up(TOUCH_PEN_DETECT_DEBOUNCE_US * adc_clk_khz /
|
||||
1000, 1);
|
||||
|
||||
while (st->ts_pendbc >> ++i)
|
||||
; /* Empty! Find the shift offset */
|
||||
if (abs(st->ts_pendbc - (1 << i)) < abs(st->ts_pendbc - (1 << (i - 1))))
|
||||
st->ts_pendbc = i;
|
||||
else
|
||||
st->ts_pendbc = i - 1;
|
||||
|
||||
if (!st->caps->has_tsmr) {
|
||||
reg = at91_adc_readl(st, AT91_ADC_MR);
|
||||
reg |= AT91_ADC_TSAMOD_TS_ONLY_MODE | AT91_ADC_PENDET;
|
||||
|
||||
reg |= AT91_ADC_PENDBC_(st->ts_pendbc) & AT91_ADC_PENDBC;
|
||||
at91_adc_writel(st, AT91_ADC_MR, reg);
|
||||
|
||||
reg = AT91_ADC_TSR_SHTIM_(TOUCH_SHTIM) & AT91_ADC_TSR_SHTIM;
|
||||
at91_adc_writel(st, AT91_ADC_TSR, reg);
|
||||
|
||||
st->ts_sample_period_val = round_up((TOUCH_SAMPLE_PERIOD_US_RL *
|
||||
adc_clk_khz / 1000) - 1, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE)
|
||||
reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS;
|
||||
else
|
||||
reg = AT91_ADC_TSMR_TSMODE_5WIRE;
|
||||
|
||||
/* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid
|
||||
* pen detect noise.
|
||||
* The formula is : Pen Detect Debounce Time = (2 ^ pendbc) / ADCClock
|
||||
*/
|
||||
pendbc = round_up(TOUCH_PEN_DETECT_DEBOUNCE_US * adc_clk_khz / 1000, 1);
|
||||
reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average)
|
||||
& AT91_ADC_TSMR_TSAV;
|
||||
reg |= AT91_ADC_TSMR_PENDBC_(st->ts_pendbc) & AT91_ADC_TSMR_PENDBC;
|
||||
reg |= AT91_ADC_TSMR_NOTSDMA;
|
||||
reg |= AT91_ADC_TSMR_PENDET_ENA;
|
||||
reg |= 0x03 << 8; /* TSFREQ, needs to be bigger than TSAV */
|
||||
|
||||
while (pendbc >> ++i)
|
||||
; /* Empty! Find the shift offset */
|
||||
if (abs(pendbc - (1 << i)) < abs(pendbc - (1 << (i - 1))))
|
||||
pendbc = i;
|
||||
else
|
||||
pendbc = i - 1;
|
||||
|
||||
if (st->caps->has_tsmr) {
|
||||
reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average)
|
||||
& AT91_ADC_TSMR_TSAV;
|
||||
reg |= AT91_ADC_TSMR_PENDBC_(pendbc) & AT91_ADC_TSMR_PENDBC;
|
||||
reg |= AT91_ADC_TSMR_NOTSDMA;
|
||||
reg |= AT91_ADC_TSMR_PENDET_ENA;
|
||||
reg |= 0x03 << 8; /* TSFREQ, need bigger than TSAV */
|
||||
|
||||
at91_adc_writel(st, AT91_ADC_TSMR, reg);
|
||||
} else {
|
||||
/* TODO: for 9g45 which has no TSMR */
|
||||
}
|
||||
at91_adc_writel(st, AT91_ADC_TSMR, reg);
|
||||
|
||||
/* Change adc internal resistor value for better pen detection,
|
||||
* default value is 100 kOhm.
|
||||
@ -845,7 +1055,7 @@ static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
|
||||
at91_adc_writel(st, AT91_ADC_ACR, st->caps->ts_pen_detect_sensitivity
|
||||
& AT91_ADC_ACR_PENDETSENS);
|
||||
|
||||
/* Sample Peroid Time = (TRGPER + 1) / ADCClock */
|
||||
/* Sample Period Time = (TRGPER + 1) / ADCClock */
|
||||
st->ts_sample_period_val = round_up((TOUCH_SAMPLE_PERIOD_US *
|
||||
adc_clk_khz / 1000) - 1, 1);
|
||||
|
||||
@ -874,18 +1084,38 @@ static int at91_ts_register(struct at91_adc_state *st,
|
||||
__set_bit(EV_ABS, input->evbit);
|
||||
__set_bit(EV_KEY, input->evbit);
|
||||
__set_bit(BTN_TOUCH, input->keybit);
|
||||
input_set_abs_params(input, ABS_X, 0, (1 << MAX_POS_BITS) - 1, 0, 0);
|
||||
input_set_abs_params(input, ABS_Y, 0, (1 << MAX_POS_BITS) - 1, 0, 0);
|
||||
input_set_abs_params(input, ABS_PRESSURE, 0, 0xffffff, 0, 0);
|
||||
if (st->caps->has_tsmr) {
|
||||
input_set_abs_params(input, ABS_X, 0, (1 << MAX_POS_BITS) - 1,
|
||||
0, 0);
|
||||
input_set_abs_params(input, ABS_Y, 0, (1 << MAX_POS_BITS) - 1,
|
||||
0, 0);
|
||||
input_set_abs_params(input, ABS_PRESSURE, 0, 0xffffff, 0, 0);
|
||||
} else {
|
||||
if (st->touchscreen_type != ATMEL_ADC_TOUCHSCREEN_4WIRE) {
|
||||
dev_err(&pdev->dev,
|
||||
"This touchscreen controller only support 4 wires\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
input_set_abs_params(input, ABS_X, 0, (1 << MAX_RLPOS_BITS) - 1,
|
||||
0, 0);
|
||||
input_set_abs_params(input, ABS_Y, 0, (1 << MAX_RLPOS_BITS) - 1,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
st->ts_input = input;
|
||||
input_set_drvdata(input, st);
|
||||
|
||||
ret = input_register_device(input);
|
||||
if (ret)
|
||||
input_free_device(st->ts_input);
|
||||
goto err;
|
||||
|
||||
return ret;
|
||||
|
||||
err:
|
||||
input_free_device(st->ts_input);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void at91_ts_unregister(struct at91_adc_state *st)
|
||||
@ -943,11 +1173,13 @@ static int at91_adc_probe(struct platform_device *pdev)
|
||||
*/
|
||||
at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_SWRST);
|
||||
at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF);
|
||||
ret = request_irq(st->irq,
|
||||
at91_adc_interrupt,
|
||||
0,
|
||||
pdev->dev.driver->name,
|
||||
idev);
|
||||
|
||||
if (st->caps->has_tsmr)
|
||||
ret = request_irq(st->irq, at91_adc_9x5_interrupt, 0,
|
||||
pdev->dev.driver->name, idev);
|
||||
else
|
||||
ret = request_irq(st->irq, at91_adc_rl_interrupt, 0,
|
||||
pdev->dev.driver->name, idev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
|
||||
return ret;
|
||||
@ -1051,12 +1283,6 @@ static int at91_adc_probe(struct platform_device *pdev)
|
||||
goto error_disable_adc_clk;
|
||||
}
|
||||
} else {
|
||||
if (!st->caps->has_tsmr) {
|
||||
dev_err(&pdev->dev, "We don't support non-TSMR adc\n");
|
||||
ret = -ENODEV;
|
||||
goto error_disable_adc_clk;
|
||||
}
|
||||
|
||||
ret = at91_ts_register(st, pdev);
|
||||
if (ret)
|
||||
goto error_disable_adc_clk;
|
||||
@ -1120,6 +1346,20 @@ static struct at91_adc_caps at91sam9260_caps = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct at91_adc_caps at91sam9rl_caps = {
|
||||
.has_ts = true,
|
||||
.calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */
|
||||
.num_channels = 6,
|
||||
.registers = {
|
||||
.channel_base = AT91_ADC_CHR(0),
|
||||
.drdy_mask = AT91_ADC_DRDY,
|
||||
.status_register = AT91_ADC_SR,
|
||||
.trigger_register = AT91_ADC_TRGR_9G45,
|
||||
.mr_prescal_mask = AT91_ADC_PRESCAL_9260,
|
||||
.mr_startup_mask = AT91_ADC_STARTUP_9G45,
|
||||
},
|
||||
};
|
||||
|
||||
static struct at91_adc_caps at91sam9g45_caps = {
|
||||
.has_ts = true,
|
||||
.calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */
|
||||
@ -1154,6 +1394,7 @@ static struct at91_adc_caps at91sam9x5_caps = {
|
||||
|
||||
static const struct of_device_id at91_adc_dt_ids[] = {
|
||||
{ .compatible = "atmel,at91sam9260-adc", .data = &at91sam9260_caps },
|
||||
{ .compatible = "atmel,at91sam9rl-adc", .data = &at91sam9rl_caps },
|
||||
{ .compatible = "atmel,at91sam9g45-adc", .data = &at91sam9g45_caps },
|
||||
{ .compatible = "atmel,at91sam9x5-adc", .data = &at91sam9x5_caps },
|
||||
{},
|
||||
@ -1164,6 +1405,9 @@ static const struct platform_device_id at91_adc_ids[] = {
|
||||
{
|
||||
.name = "at91sam9260-adc",
|
||||
.driver_data = (unsigned long)&at91sam9260_caps,
|
||||
}, {
|
||||
.name = "at91sam9rl-adc",
|
||||
.driver_data = (unsigned long)&at91sam9rl_caps,
|
||||
}, {
|
||||
.name = "at91sam9g45-adc",
|
||||
.driver_data = (unsigned long)&at91sam9g45_caps,
|
||||
|
@ -550,18 +550,6 @@ config TOUCHSCREEN_TI_AM335X_TSC
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ti_am335x_tsc.
|
||||
|
||||
config TOUCHSCREEN_ATMEL_TSADCC
|
||||
tristate "Atmel Touchscreen Interface"
|
||||
depends on ARCH_AT91
|
||||
help
|
||||
Say Y here if you have a 4-wire touchscreen connected to the
|
||||
ADC Controller on your Atmel SoC.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called atmel_tsadcc.
|
||||
|
||||
config TOUCHSCREEN_UCB1400
|
||||
tristate "Philips UCB1400 touchscreen"
|
||||
depends on AC97_BUS
|
||||
|
@ -13,7 +13,6 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
|
||||
|
@ -1,358 +0,0 @@
|
||||
/*
|
||||
* Atmel Touch Screen Driver
|
||||
*
|
||||
* Copyright (c) 2008 ATMEL
|
||||
* Copyright (c) 2008 Dan Liang
|
||||
* Copyright (c) 2008 TimeSys Corporation
|
||||
* Copyright (c) 2008 Justin Waters
|
||||
*
|
||||
* Based on touchscreen code from Atmel Corporation.
|
||||
*
|
||||
* 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/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_data/atmel.h>
|
||||
#include <mach/cpu.h>
|
||||
|
||||
/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */
|
||||
|
||||
#define ATMEL_TSADCC_CR 0x00 /* Control register */
|
||||
#define ATMEL_TSADCC_SWRST (1 << 0) /* Software Reset*/
|
||||
#define ATMEL_TSADCC_START (1 << 1) /* Start conversion */
|
||||
|
||||
#define ATMEL_TSADCC_MR 0x04 /* Mode register */
|
||||
#define ATMEL_TSADCC_TSAMOD (3 << 0) /* ADC mode */
|
||||
#define ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE (0x0) /* ADC Mode */
|
||||
#define ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE (0x1) /* Touch Screen Only Mode */
|
||||
#define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */
|
||||
#define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */
|
||||
#define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */
|
||||
#define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */
|
||||
#define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */
|
||||
#define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */
|
||||
#define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */
|
||||
#define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */
|
||||
#define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */
|
||||
|
||||
#define ATMEL_TSADCC_TRGR 0x08 /* Trigger register */
|
||||
#define ATMEL_TSADCC_TRGMOD (7 << 0) /* Trigger mode */
|
||||
#define ATMEL_TSADCC_TRGMOD_NONE (0 << 0)
|
||||
#define ATMEL_TSADCC_TRGMOD_EXT_RISING (1 << 0)
|
||||
#define ATMEL_TSADCC_TRGMOD_EXT_FALLING (2 << 0)
|
||||
#define ATMEL_TSADCC_TRGMOD_EXT_ANY (3 << 0)
|
||||
#define ATMEL_TSADCC_TRGMOD_PENDET (4 << 0)
|
||||
#define ATMEL_TSADCC_TRGMOD_PERIOD (5 << 0)
|
||||
#define ATMEL_TSADCC_TRGMOD_CONTINUOUS (6 << 0)
|
||||
#define ATMEL_TSADCC_TRGPER (0xffff << 16) /* Trigger period */
|
||||
|
||||
#define ATMEL_TSADCC_TSR 0x0C /* Touch Screen register */
|
||||
#define ATMEL_TSADCC_TSFREQ (0xf << 0) /* TS Frequency in Interleaved mode */
|
||||
#define ATMEL_TSADCC_TSSHTIM (0xf << 24) /* Sample & Hold time */
|
||||
|
||||
#define ATMEL_TSADCC_CHER 0x10 /* Channel Enable register */
|
||||
#define ATMEL_TSADCC_CHDR 0x14 /* Channel Disable register */
|
||||
#define ATMEL_TSADCC_CHSR 0x18 /* Channel Status register */
|
||||
#define ATMEL_TSADCC_CH(n) (1 << (n)) /* Channel number */
|
||||
|
||||
#define ATMEL_TSADCC_SR 0x1C /* Status register */
|
||||
#define ATMEL_TSADCC_EOC(n) (1 << ((n)+0)) /* End of conversion for channel N */
|
||||
#define ATMEL_TSADCC_OVRE(n) (1 << ((n)+8)) /* Overrun error for channel N */
|
||||
#define ATMEL_TSADCC_DRDY (1 << 16) /* Data Ready */
|
||||
#define ATMEL_TSADCC_GOVRE (1 << 17) /* General Overrun Error */
|
||||
#define ATMEL_TSADCC_ENDRX (1 << 18) /* End of RX Buffer */
|
||||
#define ATMEL_TSADCC_RXBUFF (1 << 19) /* TX Buffer full */
|
||||
#define ATMEL_TSADCC_PENCNT (1 << 20) /* Pen contact */
|
||||
#define ATMEL_TSADCC_NOCNT (1 << 21) /* No contact */
|
||||
|
||||
#define ATMEL_TSADCC_LCDR 0x20 /* Last Converted Data register */
|
||||
#define ATMEL_TSADCC_DATA (0x3ff << 0) /* Channel data */
|
||||
|
||||
#define ATMEL_TSADCC_IER 0x24 /* Interrupt Enable register */
|
||||
#define ATMEL_TSADCC_IDR 0x28 /* Interrupt Disable register */
|
||||
#define ATMEL_TSADCC_IMR 0x2C /* Interrupt Mask register */
|
||||
#define ATMEL_TSADCC_CDR0 0x30 /* Channel Data 0 */
|
||||
#define ATMEL_TSADCC_CDR1 0x34 /* Channel Data 1 */
|
||||
#define ATMEL_TSADCC_CDR2 0x38 /* Channel Data 2 */
|
||||
#define ATMEL_TSADCC_CDR3 0x3C /* Channel Data 3 */
|
||||
#define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */
|
||||
#define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */
|
||||
|
||||
#define ATMEL_TSADCC_XPOS 0x50
|
||||
#define ATMEL_TSADCC_Z1DAT 0x54
|
||||
#define ATMEL_TSADCC_Z2DAT 0x58
|
||||
|
||||
#define PRESCALER_VAL(x) ((x) >> 8)
|
||||
|
||||
#define ADC_DEFAULT_CLOCK 100000
|
||||
|
||||
struct atmel_tsadcc {
|
||||
struct input_dev *input;
|
||||
char phys[32];
|
||||
struct clk *clk;
|
||||
int irq;
|
||||
unsigned int prev_absx;
|
||||
unsigned int prev_absy;
|
||||
unsigned char bufferedmeasure;
|
||||
};
|
||||
|
||||
static void __iomem *tsc_base;
|
||||
|
||||
#define atmel_tsadcc_read(reg) __raw_readl(tsc_base + (reg))
|
||||
#define atmel_tsadcc_write(reg, val) __raw_writel((val), tsc_base + (reg))
|
||||
|
||||
static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
|
||||
{
|
||||
struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev;
|
||||
struct input_dev *input_dev = ts_dev->input;
|
||||
|
||||
unsigned int status;
|
||||
unsigned int reg;
|
||||
|
||||
status = atmel_tsadcc_read(ATMEL_TSADCC_SR);
|
||||
status &= atmel_tsadcc_read(ATMEL_TSADCC_IMR);
|
||||
|
||||
if (status & ATMEL_TSADCC_NOCNT) {
|
||||
/* Contact lost */
|
||||
reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC;
|
||||
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_IDR,
|
||||
ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
|
||||
|
||||
input_report_key(input_dev, BTN_TOUCH, 0);
|
||||
ts_dev->bufferedmeasure = 0;
|
||||
input_sync(input_dev);
|
||||
|
||||
} else if (status & ATMEL_TSADCC_PENCNT) {
|
||||
/* Pen detected */
|
||||
reg = atmel_tsadcc_read(ATMEL_TSADCC_MR);
|
||||
reg &= ~ATMEL_TSADCC_PENDBC;
|
||||
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_IER,
|
||||
ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
|
||||
ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16));
|
||||
|
||||
} else if (status & ATMEL_TSADCC_EOC(3)) {
|
||||
/* Conversion finished */
|
||||
|
||||
if (ts_dev->bufferedmeasure) {
|
||||
/* Last measurement is always discarded, since it can
|
||||
* be erroneous.
|
||||
* Always report previous measurement */
|
||||
input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
|
||||
input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
|
||||
input_report_key(input_dev, BTN_TOUCH, 1);
|
||||
input_sync(input_dev);
|
||||
} else
|
||||
ts_dev->bufferedmeasure = 1;
|
||||
|
||||
/* Now make new measurement */
|
||||
ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
|
||||
ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
|
||||
|
||||
ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
|
||||
ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* The functions for inserting/removing us as a module.
|
||||
*/
|
||||
|
||||
static int atmel_tsadcc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct atmel_tsadcc *ts_dev;
|
||||
struct input_dev *input_dev;
|
||||
struct resource *res;
|
||||
struct at91_tsadcc_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
int err;
|
||||
unsigned int prsc;
|
||||
unsigned int reg;
|
||||
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "no mmio resource defined.\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* Allocate memory for device */
|
||||
ts_dev = kzalloc(sizeof(struct atmel_tsadcc), GFP_KERNEL);
|
||||
if (!ts_dev) {
|
||||
dev_err(&pdev->dev, "failed to allocate memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
platform_set_drvdata(pdev, ts_dev);
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
dev_err(&pdev->dev, "failed to allocate input device.\n");
|
||||
err = -EBUSY;
|
||||
goto err_free_mem;
|
||||
}
|
||||
|
||||
ts_dev->irq = platform_get_irq(pdev, 0);
|
||||
if (ts_dev->irq < 0) {
|
||||
dev_err(&pdev->dev, "no irq ID is designated.\n");
|
||||
err = -ENODEV;
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
if (!request_mem_region(res->start, resource_size(res),
|
||||
"atmel tsadcc regs")) {
|
||||
dev_err(&pdev->dev, "resources is unavailable.\n");
|
||||
err = -EBUSY;
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
tsc_base = ioremap(res->start, resource_size(res));
|
||||
if (!tsc_base) {
|
||||
dev_err(&pdev->dev, "failed to map registers.\n");
|
||||
err = -ENOMEM;
|
||||
goto err_release_mem;
|
||||
}
|
||||
|
||||
err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, 0,
|
||||
pdev->dev.driver->name, ts_dev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to allocate irq.\n");
|
||||
goto err_unmap_regs;
|
||||
}
|
||||
|
||||
ts_dev->clk = clk_get(&pdev->dev, "tsc_clk");
|
||||
if (IS_ERR(ts_dev->clk)) {
|
||||
dev_err(&pdev->dev, "failed to get ts_clk\n");
|
||||
err = PTR_ERR(ts_dev->clk);
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
ts_dev->input = input_dev;
|
||||
ts_dev->bufferedmeasure = 0;
|
||||
|
||||
snprintf(ts_dev->phys, sizeof(ts_dev->phys),
|
||||
"%s/input0", dev_name(&pdev->dev));
|
||||
|
||||
input_dev->name = "atmel touch screen controller";
|
||||
input_dev->phys = ts_dev->phys;
|
||||
input_dev->dev.parent = &pdev->dev;
|
||||
|
||||
__set_bit(EV_ABS, input_dev->evbit);
|
||||
input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0);
|
||||
|
||||
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
|
||||
|
||||
/* clk_enable() always returns 0, no need to check it */
|
||||
clk_enable(ts_dev->clk);
|
||||
|
||||
prsc = clk_get_rate(ts_dev->clk);
|
||||
dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc);
|
||||
|
||||
if (!pdata->adc_clock)
|
||||
pdata->adc_clock = ADC_DEFAULT_CLOCK;
|
||||
|
||||
prsc = (prsc / (2 * pdata->adc_clock)) - 1;
|
||||
|
||||
/* saturate if this value is too high */
|
||||
if (cpu_is_at91sam9rl()) {
|
||||
if (prsc > PRESCALER_VAL(ATMEL_TSADCC_PRESCAL))
|
||||
prsc = PRESCALER_VAL(ATMEL_TSADCC_PRESCAL);
|
||||
} else {
|
||||
if (prsc > PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL))
|
||||
prsc = PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL);
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc);
|
||||
|
||||
reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE |
|
||||
((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */
|
||||
((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */
|
||||
(prsc << 8) |
|
||||
((0x26 << 16) & ATMEL_TSADCC_STARTUP) |
|
||||
((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC);
|
||||
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_TSR,
|
||||
(pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM);
|
||||
|
||||
atmel_tsadcc_read(ATMEL_TSADCC_SR);
|
||||
atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
|
||||
|
||||
/* All went ok, so register to the input system */
|
||||
err = input_register_device(input_dev);
|
||||
if (err)
|
||||
goto err_fail;
|
||||
|
||||
return 0;
|
||||
|
||||
err_fail:
|
||||
clk_disable(ts_dev->clk);
|
||||
clk_put(ts_dev->clk);
|
||||
err_free_irq:
|
||||
free_irq(ts_dev->irq, ts_dev);
|
||||
err_unmap_regs:
|
||||
iounmap(tsc_base);
|
||||
err_release_mem:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
err_free_dev:
|
||||
input_free_device(input_dev);
|
||||
err_free_mem:
|
||||
kfree(ts_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int atmel_tsadcc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct atmel_tsadcc *ts_dev = platform_get_drvdata(pdev);
|
||||
struct resource *res;
|
||||
|
||||
free_irq(ts_dev->irq, ts_dev);
|
||||
|
||||
input_unregister_device(ts_dev->input);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
iounmap(tsc_base);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
|
||||
clk_disable(ts_dev->clk);
|
||||
clk_put(ts_dev->clk);
|
||||
|
||||
kfree(ts_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver atmel_tsadcc_driver = {
|
||||
.probe = atmel_tsadcc_probe,
|
||||
.remove = atmel_tsadcc_remove,
|
||||
.driver = {
|
||||
.name = "atmel_tsadcc",
|
||||
},
|
||||
};
|
||||
module_platform_driver(atmel_tsadcc_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Atmel TouchScreen Driver");
|
||||
MODULE_AUTHOR("Dan Liang <dan.liang@atmel.com>");
|
||||
|
@ -155,6 +155,7 @@ extern void __iomem *at91_pmc_base;
|
||||
#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */
|
||||
#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */
|
||||
#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [some SAM9] */
|
||||
#define AT91_PMC_OSCSEL (1 << 7) /* Slow Oscillator Selection [some SAM9] */
|
||||
#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */
|
||||
#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */
|
||||
#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */
|
||||
|
@ -7,23 +7,10 @@
|
||||
#ifndef _AT91_ADC_H_
|
||||
#define _AT91_ADC_H_
|
||||
|
||||
/**
|
||||
* struct at91_adc_reg_desc - Various informations relative to registers
|
||||
* @channel_base: Base offset for the channel data registers
|
||||
* @drdy_mask: Mask of the DRDY field in the relevant registers
|
||||
(Interruptions registers mostly)
|
||||
* @status_register: Offset of the Interrupt Status Register
|
||||
* @trigger_register: Offset of the Trigger setup register
|
||||
* @mr_prescal_mask: Mask of the PRESCAL field in the adc MR register
|
||||
* @mr_startup_mask: Mask of the STARTUP field in the adc MR register
|
||||
*/
|
||||
struct at91_adc_reg_desc {
|
||||
u8 channel_base;
|
||||
u32 drdy_mask;
|
||||
u8 status_register;
|
||||
u8 trigger_register;
|
||||
u32 mr_prescal_mask;
|
||||
u32 mr_startup_mask;
|
||||
enum atmel_adc_ts_type {
|
||||
ATMEL_ADC_TOUCHSCREEN_NONE = 0,
|
||||
ATMEL_ADC_TOUCHSCREEN_4WIRE = 4,
|
||||
ATMEL_ADC_TOUCHSCREEN_5WIRE = 5,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -42,23 +29,21 @@ struct at91_adc_trigger {
|
||||
/**
|
||||
* struct at91_adc_data - platform data for ADC driver
|
||||
* @channels_used: channels in use on the board as a bitmask
|
||||
* @num_channels: global number of channels available on the board
|
||||
* @registers: Registers definition on the board
|
||||
* @startup_time: startup time of the ADC in microseconds
|
||||
* @trigger_list: Triggers available in the ADC
|
||||
* @trigger_number: Number of triggers available in the ADC
|
||||
* @use_external_triggers: does the board has external triggers availables
|
||||
* @vref: Reference voltage for the ADC in millivolts
|
||||
* @touchscreen_type: If a touchscreen is connected, its type (4 or 5 wires)
|
||||
*/
|
||||
struct at91_adc_data {
|
||||
unsigned long channels_used;
|
||||
u8 num_channels;
|
||||
struct at91_adc_reg_desc *registers;
|
||||
u8 startup_time;
|
||||
struct at91_adc_trigger *trigger_list;
|
||||
u8 trigger_number;
|
||||
bool use_external_triggers;
|
||||
u16 vref;
|
||||
enum atmel_adc_ts_type touchscreen_type;
|
||||
};
|
||||
|
||||
extern void __init at91_add_device_adc(struct at91_adc_data *data);
|
||||
|
@ -87,13 +87,6 @@ struct atmel_uart_data {
|
||||
int rts_gpio; /* optional RTS GPIO */
|
||||
};
|
||||
|
||||
/* Touchscreen Controller */
|
||||
struct at91_tsadcc_data {
|
||||
unsigned int adc_clock;
|
||||
u8 pendet_debounce;
|
||||
u8 ts_sample_hold_time;
|
||||
};
|
||||
|
||||
/* CAN */
|
||||
struct at91_can_data {
|
||||
void (*transceiver_switch)(int on);
|
||||
|
@ -48,7 +48,6 @@
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/gpio.h>
|
||||
|
||||
#include "../codecs/wm8731.h"
|
||||
#include "atmel-pcm.h"
|
||||
|
Loading…
Reference in New Issue
Block a user