Merge branch 'davinci-next' into davinci-for-linus
Conflicts: arch/arm/mach-davinci/board-da830-evm.c arch/arm/mach-davinci/board-da850-evm.chifive-unleashed-5.1
commit
7940a34b2e
|
@ -5303,8 +5303,8 @@ F: drivers/*/*s3c2410*
|
||||||
F: drivers/*/*/*s3c2410*
|
F: drivers/*/*/*s3c2410*
|
||||||
|
|
||||||
TI DAVINCI MACHINE SUPPORT
|
TI DAVINCI MACHINE SUPPORT
|
||||||
P: Kevin Hilman
|
M: Kevin Hilman <khilman@deeprootsystems.com>
|
||||||
M: davinci-linux-open-source@linux.davincidsp.com
|
L: davinci-linux-open-source@linux.davincidsp.com (subscribers-only)
|
||||||
Q: http://patchwork.kernel.org/project/linux-davinci/list/
|
Q: http://patchwork.kernel.org/project/linux-davinci/list/
|
||||||
S: Supported
|
S: Supported
|
||||||
F: arch/arm/mach-davinci
|
F: arch/arm/mach-davinci
|
||||||
|
|
|
@ -17,6 +17,8 @@ CONFIG_MODVERSIONS=y
|
||||||
CONFIG_ARCH_DAVINCI=y
|
CONFIG_ARCH_DAVINCI=y
|
||||||
CONFIG_ARCH_DAVINCI_DA830=y
|
CONFIG_ARCH_DAVINCI_DA830=y
|
||||||
CONFIG_ARCH_DAVINCI_DA850=y
|
CONFIG_ARCH_DAVINCI_DA850=y
|
||||||
|
CONFIG_MACH_MITYOMAPL138=y
|
||||||
|
CONFIG_MACH_OMAPL138_HAWKBOARD=y
|
||||||
CONFIG_DAVINCI_RESET_CLOCKS=y
|
CONFIG_DAVINCI_RESET_CLOCKS=y
|
||||||
CONFIG_NO_HZ=y
|
CONFIG_NO_HZ=y
|
||||||
CONFIG_HIGH_RES_TIMERS=y
|
CONFIG_HIGH_RES_TIMERS=y
|
||||||
|
@ -79,6 +81,7 @@ CONFIG_I2C_DAVINCI=y
|
||||||
# CONFIG_HWMON is not set
|
# CONFIG_HWMON is not set
|
||||||
CONFIG_WATCHDOG=y
|
CONFIG_WATCHDOG=y
|
||||||
CONFIG_REGULATOR=y
|
CONFIG_REGULATOR=y
|
||||||
|
CONFIG_REGULATOR_DUMMY=y
|
||||||
CONFIG_REGULATOR_TPS6507X=y
|
CONFIG_REGULATOR_TPS6507X=y
|
||||||
CONFIG_FB=y
|
CONFIG_FB=y
|
||||||
CONFIG_FB_DA8XX=y
|
CONFIG_FB_DA8XX=y
|
||||||
|
|
|
@ -20,23 +20,23 @@ config ARCH_DAVINCI_DM644x
|
||||||
select ARCH_DAVINCI_DMx
|
select ARCH_DAVINCI_DMx
|
||||||
|
|
||||||
config ARCH_DAVINCI_DM355
|
config ARCH_DAVINCI_DM355
|
||||||
bool "DaVinci 355 based system"
|
bool "DaVinci 355 based system"
|
||||||
select AINTC
|
select AINTC
|
||||||
select ARCH_DAVINCI_DMx
|
select ARCH_DAVINCI_DMx
|
||||||
|
|
||||||
config ARCH_DAVINCI_DM646x
|
config ARCH_DAVINCI_DM646x
|
||||||
bool "DaVinci 646x based system"
|
bool "DaVinci 646x based system"
|
||||||
select AINTC
|
select AINTC
|
||||||
select ARCH_DAVINCI_DMx
|
select ARCH_DAVINCI_DMx
|
||||||
|
|
||||||
config ARCH_DAVINCI_DA830
|
config ARCH_DAVINCI_DA830
|
||||||
bool "DA830/OMAP-L137 based system"
|
bool "DA830/OMAP-L137/AM17x based system"
|
||||||
select CP_INTC
|
select CP_INTC
|
||||||
select ARCH_DAVINCI_DA8XX
|
select ARCH_DAVINCI_DA8XX
|
||||||
select CPU_DCACHE_WRITETHROUGH # needed on silicon revs 1.0, 1.1
|
select CPU_DCACHE_WRITETHROUGH # needed on silicon revs 1.0, 1.1
|
||||||
|
|
||||||
config ARCH_DAVINCI_DA850
|
config ARCH_DAVINCI_DA850
|
||||||
bool "DA850/OMAP-L138 based system"
|
bool "DA850/OMAP-L138/AM18x based system"
|
||||||
select CP_INTC
|
select CP_INTC
|
||||||
select ARCH_DAVINCI_DA8XX
|
select ARCH_DAVINCI_DA8XX
|
||||||
select ARCH_HAS_CPUFREQ
|
select ARCH_HAS_CPUFREQ
|
||||||
|
@ -115,21 +115,21 @@ config MACH_DAVINCI_DM365_EVM
|
||||||
for development is a DM365 EVM
|
for development is a DM365 EVM
|
||||||
|
|
||||||
config MACH_DAVINCI_DA830_EVM
|
config MACH_DAVINCI_DA830_EVM
|
||||||
bool "TI DA830/OMAP-L137 Reference Platform"
|
bool "TI DA830/OMAP-L137/AM17x Reference Platform"
|
||||||
default ARCH_DAVINCI_DA830
|
default ARCH_DAVINCI_DA830
|
||||||
depends on ARCH_DAVINCI_DA830
|
depends on ARCH_DAVINCI_DA830
|
||||||
select GPIO_PCF857X
|
select GPIO_PCF857X
|
||||||
help
|
help
|
||||||
Say Y here to select the TI DA830/OMAP-L137 Evaluation Module.
|
Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module.
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Select DA830/OMAP-L137 UI board peripheral"
|
prompt "Select DA830/OMAP-L137/AM17x UI board peripheral"
|
||||||
depends on MACH_DAVINCI_DA830_EVM
|
depends on MACH_DAVINCI_DA830_EVM
|
||||||
help
|
help
|
||||||
The presence of UI card on the DA830/OMAP-L137 EVM is detected
|
The presence of UI card on the DA830/OMAP-L137/AM17x EVM is
|
||||||
automatically based on successful probe of the I2C based GPIO
|
detected automatically based on successful probe of the I2C
|
||||||
expander on that board. This option selected in this menu has
|
based GPIO expander on that board. This option selected in this
|
||||||
an effect only in case of a successful UI card detection.
|
menu has an effect only in case of a successful UI card detection.
|
||||||
|
|
||||||
config DA830_UI_LCD
|
config DA830_UI_LCD
|
||||||
bool "LCD"
|
bool "LCD"
|
||||||
|
@ -140,23 +140,23 @@ config DA830_UI_LCD
|
||||||
config DA830_UI_NAND
|
config DA830_UI_NAND
|
||||||
bool "NAND flash"
|
bool "NAND flash"
|
||||||
help
|
help
|
||||||
Say Y here to use the NAND flash. Do not forget to setup
|
Say Y here to use the NAND flash. Do not forget to setup
|
||||||
the switch correctly.
|
the switch correctly.
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config MACH_DAVINCI_DA850_EVM
|
config MACH_DAVINCI_DA850_EVM
|
||||||
bool "TI DA850/OMAP-L138 Reference Platform"
|
bool "TI DA850/OMAP-L138/AM18x Reference Platform"
|
||||||
default ARCH_DAVINCI_DA850
|
default ARCH_DAVINCI_DA850
|
||||||
depends on ARCH_DAVINCI_DA850
|
depends on ARCH_DAVINCI_DA850
|
||||||
select GPIO_PCA953X
|
select GPIO_PCA953X
|
||||||
help
|
help
|
||||||
Say Y here to select the TI DA850/OMAP-L138 Evaluation Module.
|
Say Y here to select the TI DA850/OMAP-L138/AM18x Evaluation Module.
|
||||||
|
|
||||||
choice
|
choice
|
||||||
prompt "Select peripherals connected to expander on UI board"
|
prompt "Select peripherals connected to expander on UI board"
|
||||||
depends on MACH_DAVINCI_DA850_EVM
|
depends on MACH_DAVINCI_DA850_EVM
|
||||||
help
|
help
|
||||||
The presence of User Interface (UI) card on the DA850/OMAP-L138
|
The presence of User Interface (UI) card on the DA850/OMAP-L138/AM18x
|
||||||
EVM is detected automatically based on successful probe of the I2C
|
EVM is detected automatically based on successful probe of the I2C
|
||||||
based GPIO expander on that card. This option selected in this
|
based GPIO expander on that card. This option selected in this
|
||||||
menu has an effect only in case of a successful UI card detection.
|
menu has an effect only in case of a successful UI card detection.
|
||||||
|
@ -165,13 +165,13 @@ config DA850_UI_NONE
|
||||||
bool "No peripheral is enabled"
|
bool "No peripheral is enabled"
|
||||||
help
|
help
|
||||||
Say Y if you do not want to enable any of the peripherals connected
|
Say Y if you do not want to enable any of the peripherals connected
|
||||||
to TCA6416 expander on DA850/OMAP-L138 EVM UI card
|
to TCA6416 expander on DA850/OMAP-L138/AM18x EVM UI card
|
||||||
|
|
||||||
config DA850_UI_RMII
|
config DA850_UI_RMII
|
||||||
bool "RMII Ethernet PHY"
|
bool "RMII Ethernet PHY"
|
||||||
help
|
help
|
||||||
Say Y if you want to use the RMII PHY on the DA850/OMAP-L138 EVM.
|
Say Y if you want to use the RMII PHY on the DA850/OMAP-L138/AM18x
|
||||||
This PHY is found on the UI daughter card that is supplied with
|
EVM. This PHY is found on the UI daughter card that is supplied with
|
||||||
the EVM.
|
the EVM.
|
||||||
NOTE: Please take care while choosing this option, MII PHY will
|
NOTE: Please take care while choosing this option, MII PHY will
|
||||||
not be functional if RMII mode is selected.
|
not be functional if RMII mode is selected.
|
||||||
|
@ -185,6 +185,22 @@ config MACH_TNETV107X
|
||||||
help
|
help
|
||||||
Say Y here to select the TI TNETV107X Evaluation Module.
|
Say Y here to select the TI TNETV107X Evaluation Module.
|
||||||
|
|
||||||
|
config MACH_MITYOMAPL138
|
||||||
|
bool "Critical Link MityDSP-L138/MityARM-1808 SoM"
|
||||||
|
depends on ARCH_DAVINCI_DA850
|
||||||
|
help
|
||||||
|
Say Y here to select the Critical Link MityDSP-L138/MityARM-1808
|
||||||
|
System on Module. Information on this SoM may be found at
|
||||||
|
http://www.mitydsp.com
|
||||||
|
|
||||||
|
config MACH_OMAPL138_HAWKBOARD
|
||||||
|
bool "TI AM1808 / OMAPL-138 Hawkboard platform"
|
||||||
|
depends on ARCH_DAVINCI_DA850
|
||||||
|
help
|
||||||
|
Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform .
|
||||||
|
Information of this board may be found at
|
||||||
|
http://www.hawkboard.org/
|
||||||
|
|
||||||
config DAVINCI_MUX
|
config DAVINCI_MUX
|
||||||
bool "DAVINCI multiplexing support"
|
bool "DAVINCI multiplexing support"
|
||||||
depends on ARCH_DAVINCI
|
depends on ARCH_DAVINCI
|
||||||
|
@ -195,20 +211,20 @@ config DAVINCI_MUX
|
||||||
say Y.
|
say Y.
|
||||||
|
|
||||||
config DAVINCI_MUX_DEBUG
|
config DAVINCI_MUX_DEBUG
|
||||||
bool "Multiplexing debug output"
|
bool "Multiplexing debug output"
|
||||||
depends on DAVINCI_MUX
|
depends on DAVINCI_MUX
|
||||||
help
|
help
|
||||||
Makes the multiplexing functions print out a lot of debug info.
|
Makes the multiplexing functions print out a lot of debug info.
|
||||||
This is useful if you want to find out the correct values of the
|
This is useful if you want to find out the correct values of the
|
||||||
multiplexing registers.
|
multiplexing registers.
|
||||||
|
|
||||||
config DAVINCI_MUX_WARNINGS
|
config DAVINCI_MUX_WARNINGS
|
||||||
bool "Warn about pins the bootloader didn't set up"
|
bool "Warn about pins the bootloader didn't set up"
|
||||||
depends on DAVINCI_MUX
|
depends on DAVINCI_MUX
|
||||||
help
|
help
|
||||||
Choose Y here to warn whenever driver initialization logic needs
|
Choose Y here to warn whenever driver initialization logic needs
|
||||||
to change the pin multiplexing setup. When there are no warnings
|
to change the pin multiplexing setup. When there are no warnings
|
||||||
printed, it's safe to deselect DAVINCI_MUX for your product.
|
printed, it's safe to deselect DAVINCI_MUX for your product.
|
||||||
|
|
||||||
config DAVINCI_RESET_CLOCKS
|
config DAVINCI_RESET_CLOCKS
|
||||||
bool "Reset unused clocks during boot"
|
bool "Reset unused clocks during boot"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
# Common objects
|
# Common objects
|
||||||
obj-y := time.o clock.o serial.o io.o psc.o \
|
obj-y := time.o clock.o serial.o io.o psc.o \
|
||||||
gpio.o dma.o usb.o common.o sram.o
|
gpio.o dma.o usb.o common.o sram.o aemif.o
|
||||||
|
|
||||||
obj-$(CONFIG_DAVINCI_MUX) += mux.o
|
obj-$(CONFIG_DAVINCI_MUX) += mux.o
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o
|
||||||
obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o
|
obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o
|
||||||
obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o
|
obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o
|
||||||
obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o
|
obj-$(CONFIG_MACH_TNETV107X) += board-tnetv107x-evm.o
|
||||||
|
obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o
|
||||||
|
obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o
|
||||||
|
|
||||||
# Power Management
|
# Power Management
|
||||||
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
|
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* AEMIF support for DaVinci SoCs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Texas Instruments Incorporated. http://www.ti.com/
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/time.h>
|
||||||
|
|
||||||
|
#include <mach/aemif.h>
|
||||||
|
|
||||||
|
/* Timing value configuration */
|
||||||
|
|
||||||
|
#define TA(x) ((x) << 2)
|
||||||
|
#define RHOLD(x) ((x) << 4)
|
||||||
|
#define RSTROBE(x) ((x) << 7)
|
||||||
|
#define RSETUP(x) ((x) << 13)
|
||||||
|
#define WHOLD(x) ((x) << 17)
|
||||||
|
#define WSTROBE(x) ((x) << 20)
|
||||||
|
#define WSETUP(x) ((x) << 26)
|
||||||
|
|
||||||
|
#define TA_MAX 0x3
|
||||||
|
#define RHOLD_MAX 0x7
|
||||||
|
#define RSTROBE_MAX 0x3f
|
||||||
|
#define RSETUP_MAX 0xf
|
||||||
|
#define WHOLD_MAX 0x7
|
||||||
|
#define WSTROBE_MAX 0x3f
|
||||||
|
#define WSETUP_MAX 0xf
|
||||||
|
|
||||||
|
#define TIMING_MASK (TA(TA_MAX) | \
|
||||||
|
RHOLD(RHOLD_MAX) | \
|
||||||
|
RSTROBE(RSTROBE_MAX) | \
|
||||||
|
RSETUP(RSETUP_MAX) | \
|
||||||
|
WHOLD(WHOLD_MAX) | \
|
||||||
|
WSTROBE(WSTROBE_MAX) | \
|
||||||
|
WSETUP(WSETUP_MAX))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* aemif_calc_rate - calculate timing data.
|
||||||
|
* @wanted: The cycle time needed in nanoseconds.
|
||||||
|
* @clk: The input clock rate in kHz.
|
||||||
|
* @max: The maximum divider value that can be programmed.
|
||||||
|
*
|
||||||
|
* On success, returns the calculated timing value minus 1 for easy
|
||||||
|
* programming into AEMIF timing registers, else negative errno.
|
||||||
|
*/
|
||||||
|
static int aemif_calc_rate(int wanted, unsigned long clk, int max)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1;
|
||||||
|
|
||||||
|
pr_debug("%s: result %d from %ld, %d\n", __func__, result, clk, wanted);
|
||||||
|
|
||||||
|
/* It is generally OK to have a more relaxed timing than requested... */
|
||||||
|
if (result < 0)
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
/* ... But configuring tighter timings is not an option. */
|
||||||
|
else if (result > max)
|
||||||
|
result = -EINVAL;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* davinci_aemif_setup_timing - setup timing values for a given AEMIF interface
|
||||||
|
* @t: timing values to be progammed
|
||||||
|
* @base: The virtual base address of the AEMIF interface
|
||||||
|
* @cs: chip-select to program the timing values for
|
||||||
|
*
|
||||||
|
* This function programs the given timing values (in real clock) into the
|
||||||
|
* AEMIF registers taking the AEMIF clock into account.
|
||||||
|
*
|
||||||
|
* This function does not use any locking while programming the AEMIF
|
||||||
|
* because it is expected that there is only one user of a given
|
||||||
|
* chip-select.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, else negative errno.
|
||||||
|
*/
|
||||||
|
int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
|
||||||
|
void __iomem *base, unsigned cs)
|
||||||
|
{
|
||||||
|
unsigned set, val;
|
||||||
|
unsigned ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
|
||||||
|
unsigned offset = A1CR_OFFSET + cs * 4;
|
||||||
|
struct clk *aemif_clk;
|
||||||
|
unsigned long clkrate;
|
||||||
|
|
||||||
|
if (!t)
|
||||||
|
return 0; /* Nothing to do */
|
||||||
|
|
||||||
|
aemif_clk = clk_get(NULL, "aemif");
|
||||||
|
if (IS_ERR(aemif_clk))
|
||||||
|
return PTR_ERR(aemif_clk);
|
||||||
|
|
||||||
|
clkrate = clk_get_rate(aemif_clk);
|
||||||
|
|
||||||
|
clkrate /= 1000; /* turn clock into kHz for ease of use */
|
||||||
|
|
||||||
|
ta = aemif_calc_rate(t->ta, clkrate, TA_MAX);
|
||||||
|
rhold = aemif_calc_rate(t->rhold, clkrate, RHOLD_MAX);
|
||||||
|
rstrobe = aemif_calc_rate(t->rstrobe, clkrate, RSTROBE_MAX);
|
||||||
|
rsetup = aemif_calc_rate(t->rsetup, clkrate, RSETUP_MAX);
|
||||||
|
whold = aemif_calc_rate(t->whold, clkrate, WHOLD_MAX);
|
||||||
|
wstrobe = aemif_calc_rate(t->wstrobe, clkrate, WSTROBE_MAX);
|
||||||
|
wsetup = aemif_calc_rate(t->wsetup, clkrate, WSETUP_MAX);
|
||||||
|
|
||||||
|
if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
|
||||||
|
whold < 0 || wstrobe < 0 || wsetup < 0) {
|
||||||
|
pr_err("%s: cannot get suitable timings\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) |
|
||||||
|
WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup);
|
||||||
|
|
||||||
|
val = __raw_readl(base + offset);
|
||||||
|
val &= ~TIMING_MASK;
|
||||||
|
val |= set;
|
||||||
|
__raw_writel(val, base + offset);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(davinci_aemif_setup_timing);
|
|
@ -29,10 +29,9 @@
|
||||||
#include <mach/nand.h>
|
#include <mach/nand.h>
|
||||||
#include <mach/da8xx.h>
|
#include <mach/da8xx.h>
|
||||||
#include <mach/usb.h>
|
#include <mach/usb.h>
|
||||||
|
#include <mach/aemif.h>
|
||||||
|
|
||||||
#define DA830_EVM_PHY_MASK 0x0
|
#define DA830_EVM_PHY_ID ""
|
||||||
#define DA830_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4].
|
* USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4].
|
||||||
*/
|
*/
|
||||||
|
@ -360,6 +359,16 @@ static struct nand_bbt_descr da830_evm_nand_bbt_mirror_descr = {
|
||||||
.pattern = da830_evm_nand_mirror_pattern
|
.pattern = da830_evm_nand_mirror_pattern
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct davinci_aemif_timing da830_evm_nandflash_timing = {
|
||||||
|
.wsetup = 24,
|
||||||
|
.wstrobe = 21,
|
||||||
|
.whold = 14,
|
||||||
|
.rsetup = 19,
|
||||||
|
.rstrobe = 50,
|
||||||
|
.rhold = 0,
|
||||||
|
.ta = 20,
|
||||||
|
};
|
||||||
|
|
||||||
static struct davinci_nand_pdata da830_evm_nand_pdata = {
|
static struct davinci_nand_pdata da830_evm_nand_pdata = {
|
||||||
.parts = da830_evm_nand_partitions,
|
.parts = da830_evm_nand_partitions,
|
||||||
.nr_parts = ARRAY_SIZE(da830_evm_nand_partitions),
|
.nr_parts = ARRAY_SIZE(da830_evm_nand_partitions),
|
||||||
|
@ -368,6 +377,7 @@ static struct davinci_nand_pdata da830_evm_nand_pdata = {
|
||||||
.options = NAND_USE_FLASH_BBT,
|
.options = NAND_USE_FLASH_BBT,
|
||||||
.bbt_td = &da830_evm_nand_bbt_main_descr,
|
.bbt_td = &da830_evm_nand_bbt_main_descr,
|
||||||
.bbt_md = &da830_evm_nand_bbt_mirror_descr,
|
.bbt_md = &da830_evm_nand_bbt_mirror_descr,
|
||||||
|
.timing = &da830_evm_nandflash_timing,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct resource da830_evm_nand_resources[] = {
|
static struct resource da830_evm_nand_resources[] = {
|
||||||
|
@ -546,9 +556,8 @@ static __init void da830_evm_init(void)
|
||||||
|
|
||||||
da830_evm_usb_init();
|
da830_evm_usb_init();
|
||||||
|
|
||||||
soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK;
|
|
||||||
soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY;
|
|
||||||
soc_info->emac_pdata->rmii_en = 1;
|
soc_info->emac_pdata->rmii_en = 1;
|
||||||
|
soc_info->emac_pdata->phy_id = DA830_EVM_PHY_ID;
|
||||||
|
|
||||||
ret = davinci_cfg_reg_list(da830_cpgmac_pins);
|
ret = davinci_cfg_reg_list(da830_cpgmac_pins);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -586,6 +595,9 @@ static __init void da830_evm_init(void)
|
||||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||||
static int __init da830_evm_console_init(void)
|
static int __init da830_evm_console_init(void)
|
||||||
{
|
{
|
||||||
|
if (!machine_is_davinci_da830_evm())
|
||||||
|
return 0;
|
||||||
|
|
||||||
return add_preferred_console("ttyS", 2, "115200");
|
return add_preferred_console("ttyS", 2, "115200");
|
||||||
}
|
}
|
||||||
console_initcall(da830_evm_console_init);
|
console_initcall(da830_evm_console_init);
|
||||||
|
@ -596,7 +608,7 @@ static void __init da830_evm_map_io(void)
|
||||||
da830_init();
|
da830_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137 EVM")
|
MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
|
||||||
.boot_params = (DA8XX_DDR_BASE + 0x100),
|
.boot_params = (DA8XX_DDR_BASE + 0x100),
|
||||||
.map_io = da830_evm_map_io,
|
.map_io = da830_evm_map_io,
|
||||||
.init_irq = cp_intc_init,
|
.init_irq = cp_intc_init,
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <linux/mtd/physmap.h>
|
#include <linux/mtd/physmap.h>
|
||||||
#include <linux/regulator/machine.h>
|
#include <linux/regulator/machine.h>
|
||||||
#include <linux/regulator/tps6507x.h>
|
#include <linux/regulator/tps6507x.h>
|
||||||
#include <linux/mfd/tps6507x.h>
|
|
||||||
#include <linux/input/tps6507x-ts.h>
|
#include <linux/input/tps6507x-ts.h>
|
||||||
|
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
|
@ -36,10 +35,9 @@
|
||||||
#include <mach/da8xx.h>
|
#include <mach/da8xx.h>
|
||||||
#include <mach/nand.h>
|
#include <mach/nand.h>
|
||||||
#include <mach/mux.h>
|
#include <mach/mux.h>
|
||||||
|
#include <mach/aemif.h>
|
||||||
|
|
||||||
#define DA850_EVM_PHY_MASK 0x1
|
#define DA850_EVM_PHY_ID "0:00"
|
||||||
#define DA850_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */
|
|
||||||
|
|
||||||
#define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8)
|
#define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8)
|
||||||
#define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15)
|
#define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15)
|
||||||
|
|
||||||
|
@ -110,7 +108,7 @@ static struct platform_device da850_pm_device = {
|
||||||
* to boot, using TI's tools to install the secondary boot loader
|
* to boot, using TI's tools to install the secondary boot loader
|
||||||
* (UBL) and U-Boot.
|
* (UBL) and U-Boot.
|
||||||
*/
|
*/
|
||||||
struct mtd_partition da850_evm_nandflash_partition[] = {
|
static struct mtd_partition da850_evm_nandflash_partition[] = {
|
||||||
{
|
{
|
||||||
.name = "u-boot env",
|
.name = "u-boot env",
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
|
@ -143,12 +141,23 @@ struct mtd_partition da850_evm_nandflash_partition[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct davinci_aemif_timing da850_evm_nandflash_timing = {
|
||||||
|
.wsetup = 24,
|
||||||
|
.wstrobe = 21,
|
||||||
|
.whold = 14,
|
||||||
|
.rsetup = 19,
|
||||||
|
.rstrobe = 50,
|
||||||
|
.rhold = 0,
|
||||||
|
.ta = 20,
|
||||||
|
};
|
||||||
|
|
||||||
static struct davinci_nand_pdata da850_evm_nandflash_data = {
|
static struct davinci_nand_pdata da850_evm_nandflash_data = {
|
||||||
.parts = da850_evm_nandflash_partition,
|
.parts = da850_evm_nandflash_partition,
|
||||||
.nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition),
|
.nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition),
|
||||||
.ecc_mode = NAND_ECC_HW,
|
.ecc_mode = NAND_ECC_HW,
|
||||||
.ecc_bits = 4,
|
.ecc_bits = 4,
|
||||||
.options = NAND_USE_FLASH_BBT,
|
.options = NAND_USE_FLASH_BBT,
|
||||||
|
.timing = &da850_evm_nandflash_timing,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct resource da850_evm_nandflash_resource[] = {
|
static struct resource da850_evm_nandflash_resource[] = {
|
||||||
|
@ -196,6 +205,30 @@ static void __init da850_evm_init_nor(void)
|
||||||
iounmap(aemif_addr);
|
iounmap(aemif_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const short da850_evm_nand_pins[] = {
|
||||||
|
DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
|
||||||
|
DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
|
||||||
|
DA850_EMA_A_1, DA850_EMA_A_2, DA850_NEMA_CS_3, DA850_NEMA_CS_4,
|
||||||
|
DA850_NEMA_WE, DA850_NEMA_OE,
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const short da850_evm_nor_pins[] = {
|
||||||
|
DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
|
||||||
|
DA850_NEMA_WE, DA850_NEMA_OE, DA850_EMA_D_0, DA850_EMA_D_1,
|
||||||
|
DA850_EMA_D_2, DA850_EMA_D_3, DA850_EMA_D_4, DA850_EMA_D_5,
|
||||||
|
DA850_EMA_D_6, DA850_EMA_D_7, DA850_EMA_D_8, DA850_EMA_D_9,
|
||||||
|
DA850_EMA_D_10, DA850_EMA_D_11, DA850_EMA_D_12, DA850_EMA_D_13,
|
||||||
|
DA850_EMA_D_14, DA850_EMA_D_15, DA850_EMA_A_0, DA850_EMA_A_1,
|
||||||
|
DA850_EMA_A_2, DA850_EMA_A_3, DA850_EMA_A_4, DA850_EMA_A_5,
|
||||||
|
DA850_EMA_A_6, DA850_EMA_A_7, DA850_EMA_A_8, DA850_EMA_A_9,
|
||||||
|
DA850_EMA_A_10, DA850_EMA_A_11, DA850_EMA_A_12, DA850_EMA_A_13,
|
||||||
|
DA850_EMA_A_14, DA850_EMA_A_15, DA850_EMA_A_16, DA850_EMA_A_17,
|
||||||
|
DA850_EMA_A_18, DA850_EMA_A_19, DA850_EMA_A_20, DA850_EMA_A_21,
|
||||||
|
DA850_EMA_A_22, DA850_EMA_A_23,
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
static u32 ui_card_detected;
|
static u32 ui_card_detected;
|
||||||
|
|
||||||
#if defined(CONFIG_MMC_DAVINCI) || \
|
#if defined(CONFIG_MMC_DAVINCI) || \
|
||||||
|
@ -205,17 +238,17 @@ static u32 ui_card_detected;
|
||||||
#define HAS_MMC 0
|
#define HAS_MMC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static __init void da850_evm_setup_nor_nand(void)
|
static inline void da850_evm_setup_nor_nand(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (ui_card_detected & !HAS_MMC) {
|
if (ui_card_detected & !HAS_MMC) {
|
||||||
ret = davinci_cfg_reg_list(da850_nand_pins);
|
ret = davinci_cfg_reg_list(da850_evm_nand_pins);
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_warning("da850_evm_init: nand mux setup failed: "
|
pr_warning("da850_evm_init: nand mux setup failed: "
|
||||||
"%d\n", ret);
|
"%d\n", ret);
|
||||||
|
|
||||||
ret = davinci_cfg_reg_list(da850_nor_pins);
|
ret = davinci_cfg_reg_list(da850_evm_nor_pins);
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_warning("da850_evm_init: nor mux setup failed: %d\n",
|
pr_warning("da850_evm_init: nor mux setup failed: %d\n",
|
||||||
ret);
|
ret);
|
||||||
|
@ -406,7 +439,7 @@ static int da850_lcd_hw_init(void)
|
||||||
/* TPS65070 voltage regulator support */
|
/* TPS65070 voltage regulator support */
|
||||||
|
|
||||||
/* 3.3V */
|
/* 3.3V */
|
||||||
struct regulator_consumer_supply tps65070_dcdc1_consumers[] = {
|
static struct regulator_consumer_supply tps65070_dcdc1_consumers[] = {
|
||||||
{
|
{
|
||||||
.supply = "usb0_vdda33",
|
.supply = "usb0_vdda33",
|
||||||
},
|
},
|
||||||
|
@ -416,7 +449,7 @@ struct regulator_consumer_supply tps65070_dcdc1_consumers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 3.3V or 1.8V */
|
/* 3.3V or 1.8V */
|
||||||
struct regulator_consumer_supply tps65070_dcdc2_consumers[] = {
|
static struct regulator_consumer_supply tps65070_dcdc2_consumers[] = {
|
||||||
{
|
{
|
||||||
.supply = "dvdd3318_a",
|
.supply = "dvdd3318_a",
|
||||||
},
|
},
|
||||||
|
@ -429,14 +462,14 @@ struct regulator_consumer_supply tps65070_dcdc2_consumers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 1.2V */
|
/* 1.2V */
|
||||||
struct regulator_consumer_supply tps65070_dcdc3_consumers[] = {
|
static struct regulator_consumer_supply tps65070_dcdc3_consumers[] = {
|
||||||
{
|
{
|
||||||
.supply = "cvdd",
|
.supply = "cvdd",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 1.8V LDO */
|
/* 1.8V LDO */
|
||||||
struct regulator_consumer_supply tps65070_ldo1_consumers[] = {
|
static struct regulator_consumer_supply tps65070_ldo1_consumers[] = {
|
||||||
{
|
{
|
||||||
.supply = "sata_vddr",
|
.supply = "sata_vddr",
|
||||||
},
|
},
|
||||||
|
@ -452,7 +485,7 @@ struct regulator_consumer_supply tps65070_ldo1_consumers[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 1.2V LDO */
|
/* 1.2V LDO */
|
||||||
struct regulator_consumer_supply tps65070_ldo2_consumers[] = {
|
static struct regulator_consumer_supply tps65070_ldo2_consumers[] = {
|
||||||
{
|
{
|
||||||
.supply = "sata_vdd",
|
.supply = "sata_vdd",
|
||||||
},
|
},
|
||||||
|
@ -475,7 +508,7 @@ static struct tps6507x_reg_platform_data tps6507x_platform_data = {
|
||||||
.defdcdc_default = true,
|
.defdcdc_default = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct regulator_init_data tps65070_regulator_data[] = {
|
static struct regulator_init_data tps65070_regulator_data[] = {
|
||||||
/* dcdc1 */
|
/* dcdc1 */
|
||||||
{
|
{
|
||||||
.constraints = {
|
.constraints = {
|
||||||
|
@ -576,6 +609,23 @@ static const short da850_evm_lcdc_pins[] = {
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const short da850_evm_mii_pins[] = {
|
||||||
|
DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
|
||||||
|
DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
|
||||||
|
DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
|
||||||
|
DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
|
||||||
|
DA850_MDIO_D,
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const short da850_evm_rmii_pins[] = {
|
||||||
|
DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
|
||||||
|
DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
|
||||||
|
DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
|
||||||
|
DA850_MDIO_D,
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
static int __init da850_evm_config_emac(void)
|
static int __init da850_evm_config_emac(void)
|
||||||
{
|
{
|
||||||
void __iomem *cfg_chip3_base;
|
void __iomem *cfg_chip3_base;
|
||||||
|
@ -593,12 +643,12 @@ static int __init da850_evm_config_emac(void)
|
||||||
|
|
||||||
if (rmii_en) {
|
if (rmii_en) {
|
||||||
val |= BIT(8);
|
val |= BIT(8);
|
||||||
ret = davinci_cfg_reg_list(da850_rmii_pins);
|
ret = davinci_cfg_reg_list(da850_evm_rmii_pins);
|
||||||
pr_info("EMAC: RMII PHY configured, MII PHY will not be"
|
pr_info("EMAC: RMII PHY configured, MII PHY will not be"
|
||||||
" functional\n");
|
" functional\n");
|
||||||
} else {
|
} else {
|
||||||
val &= ~BIT(8);
|
val &= ~BIT(8);
|
||||||
ret = davinci_cfg_reg_list(da850_cpgmac_pins);
|
ret = davinci_cfg_reg_list(da850_evm_mii_pins);
|
||||||
pr_info("EMAC: MII PHY configured, RMII PHY will not be"
|
pr_info("EMAC: MII PHY configured, RMII PHY will not be"
|
||||||
" functional\n");
|
" functional\n");
|
||||||
}
|
}
|
||||||
|
@ -625,8 +675,7 @@ static int __init da850_evm_config_emac(void)
|
||||||
/* Enable/Disable MII MDIO clock */
|
/* Enable/Disable MII MDIO clock */
|
||||||
gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en);
|
gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en);
|
||||||
|
|
||||||
soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK;
|
soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID;
|
||||||
soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY;
|
|
||||||
|
|
||||||
ret = da8xx_register_emac();
|
ret = da8xx_register_emac();
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -787,7 +836,7 @@ static __init void da850_evm_init(void)
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_warning("da850_evm_init: rtc setup failed: %d\n", ret);
|
pr_warning("da850_evm_init: rtc setup failed: %d\n", ret);
|
||||||
|
|
||||||
ret = da850_register_cpufreq();
|
ret = da850_register_cpufreq("pll0_sysclk3");
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_warning("da850_evm_init: cpufreq registration failed: %d\n",
|
pr_warning("da850_evm_init: cpufreq registration failed: %d\n",
|
||||||
ret);
|
ret);
|
||||||
|
@ -806,6 +855,9 @@ static __init void da850_evm_init(void)
|
||||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||||
static int __init da850_evm_console_init(void)
|
static int __init da850_evm_console_init(void)
|
||||||
{
|
{
|
||||||
|
if (!machine_is_davinci_da850_evm())
|
||||||
|
return 0;
|
||||||
|
|
||||||
return add_preferred_console("ttyS", 2, "115200");
|
return add_preferred_console("ttyS", 2, "115200");
|
||||||
}
|
}
|
||||||
console_initcall(da850_evm_console_init);
|
console_initcall(da850_evm_console_init);
|
||||||
|
@ -816,7 +868,7 @@ static void __init da850_evm_map_io(void)
|
||||||
da850_init();
|
da850_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138 EVM")
|
MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
|
||||||
.boot_params = (DA8XX_DDR_BASE + 0x100),
|
.boot_params = (DA8XX_DDR_BASE + 0x100),
|
||||||
.map_io = da850_evm_map_io,
|
.map_io = da850_evm_map_io,
|
||||||
.init_irq = cp_intc_init,
|
.init_irq = cp_intc_init,
|
||||||
|
|
|
@ -54,9 +54,7 @@ static inline int have_tvp7002(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DM365_EVM_PHY_MASK (0x2)
|
#define DM365_EVM_PHY_ID "0:01"
|
||||||
#define DM365_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A MAX-II CPLD is used for various board control functions.
|
* A MAX-II CPLD is used for various board control functions.
|
||||||
*/
|
*/
|
||||||
|
@ -175,7 +173,9 @@ static struct at24_platform_data eeprom_info = {
|
||||||
.context = (void *)0x7f00,
|
.context = (void *)0x7f00,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_platform_data dm365_evm_snd_data;
|
static struct snd_platform_data dm365_evm_snd_data = {
|
||||||
|
.asp_chan_q = EVENTQ_3,
|
||||||
|
};
|
||||||
|
|
||||||
static struct i2c_board_info i2c_info[] = {
|
static struct i2c_board_info i2c_info[] = {
|
||||||
{
|
{
|
||||||
|
@ -533,8 +533,7 @@ fail:
|
||||||
|
|
||||||
/* ... and ENET ... */
|
/* ... and ENET ... */
|
||||||
dm365evm_emac_configure();
|
dm365evm_emac_configure();
|
||||||
soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK;
|
soc_info->emac_pdata->phy_id = DM365_EVM_PHY_ID;
|
||||||
soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY;
|
|
||||||
resets &= ~BIT(3);
|
resets &= ~BIT(3);
|
||||||
|
|
||||||
/* ... and AIC33 */
|
/* ... and AIC33 */
|
||||||
|
|
|
@ -37,10 +37,9 @@
|
||||||
#include <mach/nand.h>
|
#include <mach/nand.h>
|
||||||
#include <mach/mmc.h>
|
#include <mach/mmc.h>
|
||||||
#include <mach/usb.h>
|
#include <mach/usb.h>
|
||||||
|
#include <mach/aemif.h>
|
||||||
|
|
||||||
#define DM644X_EVM_PHY_MASK (0x2)
|
#define DM644X_EVM_PHY_ID "0:01"
|
||||||
#define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */
|
|
||||||
|
|
||||||
#define LXT971_PHY_ID (0x001378e2)
|
#define LXT971_PHY_ID (0x001378e2)
|
||||||
#define LXT971_PHY_MASK (0xfffffff0)
|
#define LXT971_PHY_MASK (0xfffffff0)
|
||||||
|
|
||||||
|
@ -137,11 +136,22 @@ static struct mtd_partition davinci_evm_nandflash_partition[] = {
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct davinci_aemif_timing davinci_evm_nandflash_timing = {
|
||||||
|
.wsetup = 20,
|
||||||
|
.wstrobe = 40,
|
||||||
|
.whold = 20,
|
||||||
|
.rsetup = 10,
|
||||||
|
.rstrobe = 40,
|
||||||
|
.rhold = 10,
|
||||||
|
.ta = 40,
|
||||||
|
};
|
||||||
|
|
||||||
static struct davinci_nand_pdata davinci_evm_nandflash_data = {
|
static struct davinci_nand_pdata davinci_evm_nandflash_data = {
|
||||||
.parts = davinci_evm_nandflash_partition,
|
.parts = davinci_evm_nandflash_partition,
|
||||||
.nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition),
|
.nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition),
|
||||||
.ecc_mode = NAND_ECC_HW,
|
.ecc_mode = NAND_ECC_HW,
|
||||||
.options = NAND_USE_FLASH_BBT,
|
.options = NAND_USE_FLASH_BBT,
|
||||||
|
.timing = &davinci_evm_nandflash_timing,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct resource davinci_evm_nandflash_resource[] = {
|
static struct resource davinci_evm_nandflash_resource[] = {
|
||||||
|
@ -695,9 +705,7 @@ static __init void davinci_evm_init(void)
|
||||||
davinci_serial_init(&uart_config);
|
davinci_serial_init(&uart_config);
|
||||||
dm644x_init_asp(&dm644x_evm_snd_data);
|
dm644x_init_asp(&dm644x_evm_snd_data);
|
||||||
|
|
||||||
soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK;
|
soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID;
|
||||||
soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY;
|
|
||||||
|
|
||||||
/* Register the fixup for PHY on DaVinci */
|
/* Register the fixup for PHY on DaVinci */
|
||||||
phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
|
phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
|
||||||
davinci_phy_fixup);
|
davinci_phy_fixup);
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <mach/nand.h>
|
#include <mach/nand.h>
|
||||||
#include <mach/clock.h>
|
#include <mach/clock.h>
|
||||||
#include <mach/cdce949.h>
|
#include <mach/cdce949.h>
|
||||||
|
#include <mach/aemif.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
|
||||||
|
@ -71,6 +72,16 @@ static struct mtd_partition davinci_nand_partitions[] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct davinci_aemif_timing dm6467tevm_nandflash_timing = {
|
||||||
|
.wsetup = 29,
|
||||||
|
.wstrobe = 24,
|
||||||
|
.whold = 14,
|
||||||
|
.rsetup = 19,
|
||||||
|
.rstrobe = 33,
|
||||||
|
.rhold = 0,
|
||||||
|
.ta = 29,
|
||||||
|
};
|
||||||
|
|
||||||
static struct davinci_nand_pdata davinci_nand_data = {
|
static struct davinci_nand_pdata davinci_nand_data = {
|
||||||
.mask_cle = 0x80000,
|
.mask_cle = 0x80000,
|
||||||
.mask_ale = 0x40000,
|
.mask_ale = 0x40000,
|
||||||
|
@ -718,9 +729,7 @@ static struct davinci_uart_config uart_config __initdata = {
|
||||||
.enabled_uarts = (1 << 0),
|
.enabled_uarts = (1 << 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DM646X_EVM_PHY_MASK (0x2)
|
#define DM646X_EVM_PHY_ID "0:01"
|
||||||
#define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following EDMA channels/slots are not being used by drivers (for
|
* The following EDMA channels/slots are not being used by drivers (for
|
||||||
* example: Timer, GPIO, UART events etc) on dm646x, hence they are being
|
* example: Timer, GPIO, UART events etc) on dm646x, hence they are being
|
||||||
|
@ -763,6 +772,9 @@ static __init void evm_init(void)
|
||||||
dm646x_init_mcasp0(&dm646x_evm_snd_data[0]);
|
dm646x_init_mcasp0(&dm646x_evm_snd_data[0]);
|
||||||
dm646x_init_mcasp1(&dm646x_evm_snd_data[1]);
|
dm646x_init_mcasp1(&dm646x_evm_snd_data[1]);
|
||||||
|
|
||||||
|
if (machine_is_davinci_dm6467tevm())
|
||||||
|
davinci_nand_data.timing = &dm6467tevm_nandflash_timing;
|
||||||
|
|
||||||
platform_device_register(&davinci_nand_device);
|
platform_device_register(&davinci_nand_device);
|
||||||
|
|
||||||
dm646x_init_edma(dm646x_edma_rsv);
|
dm646x_init_edma(dm646x_edma_rsv);
|
||||||
|
@ -770,8 +782,7 @@ static __init void evm_init(void)
|
||||||
if (HAS_ATA)
|
if (HAS_ATA)
|
||||||
davinci_init_ide();
|
davinci_init_ide();
|
||||||
|
|
||||||
soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK;
|
soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID;
|
||||||
soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DM646X_EVM_REF_FREQ 27000000
|
#define DM646X_EVM_REF_FREQ 27000000
|
||||||
|
|
|
@ -0,0 +1,424 @@
|
||||||
|
/*
|
||||||
|
* Critical Link MityOMAP-L138 SoM
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Critical Link LLC - http://www.criticallink.com
|
||||||
|
*
|
||||||
|
* This file is licensed under the terms of the GNU General Public License
|
||||||
|
* version 2. This program is licensed "as is" without any warranty of
|
||||||
|
* any kind, whether express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/console.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/mtd/partitions.h>
|
||||||
|
#include <linux/regulator/machine.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c/at24.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
#include <asm/mach/arch.h>
|
||||||
|
#include <mach/common.h>
|
||||||
|
#include <mach/cp_intc.h>
|
||||||
|
#include <mach/da8xx.h>
|
||||||
|
#include <mach/nand.h>
|
||||||
|
#include <mach/mux.h>
|
||||||
|
|
||||||
|
#define MITYOMAPL138_PHY_ID "0:03"
|
||||||
|
|
||||||
|
#define FACTORY_CONFIG_MAGIC 0x012C0138
|
||||||
|
#define FACTORY_CONFIG_VERSION 0x00010001
|
||||||
|
|
||||||
|
/* Data Held in On-Board I2C device */
|
||||||
|
struct factory_config {
|
||||||
|
u32 magic;
|
||||||
|
u32 version;
|
||||||
|
u8 mac[6];
|
||||||
|
u32 fpga_type;
|
||||||
|
u32 spare;
|
||||||
|
u32 serialnumber;
|
||||||
|
char partnum[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct factory_config factory_config;
|
||||||
|
|
||||||
|
static void read_factory_config(struct memory_accessor *a, void *context)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct davinci_soc_info *soc_info = &davinci_soc_info;
|
||||||
|
|
||||||
|
ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config));
|
||||||
|
if (ret != sizeof(struct factory_config)) {
|
||||||
|
pr_warning("MityOMAPL138: Read Factory Config Failed: %d\n",
|
||||||
|
ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (factory_config.magic != FACTORY_CONFIG_MAGIC) {
|
||||||
|
pr_warning("MityOMAPL138: Factory Config Magic Wrong (%X)\n",
|
||||||
|
factory_config.magic);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (factory_config.version != FACTORY_CONFIG_VERSION) {
|
||||||
|
pr_warning("MityOMAPL138: Factory Config Version Wrong (%X)\n",
|
||||||
|
factory_config.version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info("MityOMAPL138: Found MAC = %pM\n", factory_config.mac);
|
||||||
|
pr_info("MityOMAPL138: Part Number = %s\n", factory_config.partnum);
|
||||||
|
if (is_valid_ether_addr(factory_config.mac))
|
||||||
|
memcpy(soc_info->emac_pdata->mac_addr,
|
||||||
|
factory_config.mac, ETH_ALEN);
|
||||||
|
else
|
||||||
|
pr_warning("MityOMAPL138: Invalid MAC found "
|
||||||
|
"in factory config block\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct at24_platform_data mityomapl138_fd_chip = {
|
||||||
|
.byte_len = 256,
|
||||||
|
.page_size = 8,
|
||||||
|
.flags = AT24_FLAG_READONLY | AT24_FLAG_IRUGO,
|
||||||
|
.setup = read_factory_config,
|
||||||
|
.context = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = {
|
||||||
|
.bus_freq = 100, /* kHz */
|
||||||
|
.bus_delay = 0, /* usec */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TPS65023 voltage regulator support */
|
||||||
|
/* 1.2V Core */
|
||||||
|
static struct regulator_consumer_supply tps65023_dcdc1_consumers[] = {
|
||||||
|
{
|
||||||
|
.supply = "cvdd",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 1.8V */
|
||||||
|
static struct regulator_consumer_supply tps65023_dcdc2_consumers[] = {
|
||||||
|
{
|
||||||
|
.supply = "usb0_vdda18",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.supply = "usb1_vdda18",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.supply = "ddr_dvdd18",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.supply = "sata_vddr",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 1.2V */
|
||||||
|
static struct regulator_consumer_supply tps65023_dcdc3_consumers[] = {
|
||||||
|
{
|
||||||
|
.supply = "sata_vdd",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.supply = "usb_cvdd",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.supply = "pll0_vdda",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.supply = "pll1_vdda",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 1.8V Aux LDO, not used */
|
||||||
|
static struct regulator_consumer_supply tps65023_ldo1_consumers[] = {
|
||||||
|
{
|
||||||
|
.supply = "1.8v_aux",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FPGA VCC Aux (2.5 or 3.3) LDO */
|
||||||
|
static struct regulator_consumer_supply tps65023_ldo2_consumers[] = {
|
||||||
|
{
|
||||||
|
.supply = "vccaux",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct regulator_init_data tps65023_regulator_data[] = {
|
||||||
|
/* dcdc1 */
|
||||||
|
{
|
||||||
|
.constraints = {
|
||||||
|
.min_uV = 1150000,
|
||||||
|
.max_uV = 1350000,
|
||||||
|
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
|
||||||
|
REGULATOR_CHANGE_STATUS,
|
||||||
|
.boot_on = 1,
|
||||||
|
},
|
||||||
|
.num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc1_consumers),
|
||||||
|
.consumer_supplies = tps65023_dcdc1_consumers,
|
||||||
|
},
|
||||||
|
/* dcdc2 */
|
||||||
|
{
|
||||||
|
.constraints = {
|
||||||
|
.min_uV = 1800000,
|
||||||
|
.max_uV = 1800000,
|
||||||
|
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
||||||
|
.boot_on = 1,
|
||||||
|
},
|
||||||
|
.num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc2_consumers),
|
||||||
|
.consumer_supplies = tps65023_dcdc2_consumers,
|
||||||
|
},
|
||||||
|
/* dcdc3 */
|
||||||
|
{
|
||||||
|
.constraints = {
|
||||||
|
.min_uV = 1200000,
|
||||||
|
.max_uV = 1200000,
|
||||||
|
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
||||||
|
.boot_on = 1,
|
||||||
|
},
|
||||||
|
.num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc3_consumers),
|
||||||
|
.consumer_supplies = tps65023_dcdc3_consumers,
|
||||||
|
},
|
||||||
|
/* ldo1 */
|
||||||
|
{
|
||||||
|
.constraints = {
|
||||||
|
.min_uV = 1800000,
|
||||||
|
.max_uV = 1800000,
|
||||||
|
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
||||||
|
.boot_on = 1,
|
||||||
|
},
|
||||||
|
.num_consumer_supplies = ARRAY_SIZE(tps65023_ldo1_consumers),
|
||||||
|
.consumer_supplies = tps65023_ldo1_consumers,
|
||||||
|
},
|
||||||
|
/* ldo2 */
|
||||||
|
{
|
||||||
|
.constraints = {
|
||||||
|
.min_uV = 2500000,
|
||||||
|
.max_uV = 3300000,
|
||||||
|
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
|
||||||
|
REGULATOR_CHANGE_STATUS,
|
||||||
|
.boot_on = 1,
|
||||||
|
},
|
||||||
|
.num_consumer_supplies = ARRAY_SIZE(tps65023_ldo2_consumers),
|
||||||
|
.consumer_supplies = tps65023_ldo2_consumers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_board_info __initdata mityomap_tps65023_info[] = {
|
||||||
|
{
|
||||||
|
I2C_BOARD_INFO("tps65023", 0x48),
|
||||||
|
.platform_data = &tps65023_regulator_data[0],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
I2C_BOARD_INFO("24c02", 0x50),
|
||||||
|
.platform_data = &mityomapl138_fd_chip,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init pmic_tps65023_init(void)
|
||||||
|
{
|
||||||
|
return i2c_register_board_info(1, mityomap_tps65023_info,
|
||||||
|
ARRAY_SIZE(mityomap_tps65023_info));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MityDSP-L138 includes a 256 MByte large-page NAND flash
|
||||||
|
* (128K blocks).
|
||||||
|
*/
|
||||||
|
static struct mtd_partition mityomapl138_nandflash_partition[] = {
|
||||||
|
{
|
||||||
|
.name = "rootfs",
|
||||||
|
.offset = 0,
|
||||||
|
.size = SZ_128M,
|
||||||
|
.mask_flags = 0, /* MTD_WRITEABLE, */
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "homefs",
|
||||||
|
.offset = MTDPART_OFS_APPEND,
|
||||||
|
.size = MTDPART_SIZ_FULL,
|
||||||
|
.mask_flags = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct davinci_nand_pdata mityomapl138_nandflash_data = {
|
||||||
|
.parts = mityomapl138_nandflash_partition,
|
||||||
|
.nr_parts = ARRAY_SIZE(mityomapl138_nandflash_partition),
|
||||||
|
.ecc_mode = NAND_ECC_HW,
|
||||||
|
.options = NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16,
|
||||||
|
.ecc_bits = 1, /* 4 bit mode is not supported with 16 bit NAND */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct resource mityomapl138_nandflash_resource[] = {
|
||||||
|
{
|
||||||
|
.start = DA8XX_AEMIF_CS3_BASE,
|
||||||
|
.end = DA8XX_AEMIF_CS3_BASE + SZ_512K + 2 * SZ_1K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.start = DA8XX_AEMIF_CTL_BASE,
|
||||||
|
.end = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device mityomapl138_nandflash_device = {
|
||||||
|
.name = "davinci_nand",
|
||||||
|
.id = 0,
|
||||||
|
.dev = {
|
||||||
|
.platform_data = &mityomapl138_nandflash_data,
|
||||||
|
},
|
||||||
|
.num_resources = ARRAY_SIZE(mityomapl138_nandflash_resource),
|
||||||
|
.resource = mityomapl138_nandflash_resource,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device *mityomapl138_devices[] __initdata = {
|
||||||
|
&mityomapl138_nandflash_device,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init mityomapl138_setup_nand(void)
|
||||||
|
{
|
||||||
|
platform_add_devices(mityomapl138_devices,
|
||||||
|
ARRAY_SIZE(mityomapl138_devices));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct davinci_uart_config mityomapl138_uart_config __initdata = {
|
||||||
|
.enabled_uarts = 0x7,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const short mityomap_mii_pins[] = {
|
||||||
|
DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
|
||||||
|
DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
|
||||||
|
DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
|
||||||
|
DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
|
||||||
|
DA850_MDIO_D,
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const short mityomap_rmii_pins[] = {
|
||||||
|
DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
|
||||||
|
DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
|
||||||
|
DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
|
||||||
|
DA850_MDIO_D,
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init mityomapl138_config_emac(void)
|
||||||
|
{
|
||||||
|
void __iomem *cfg_chip3_base;
|
||||||
|
int ret;
|
||||||
|
u32 val;
|
||||||
|
struct davinci_soc_info *soc_info = &davinci_soc_info;
|
||||||
|
|
||||||
|
soc_info->emac_pdata->rmii_en = 0; /* hardcoded for now */
|
||||||
|
|
||||||
|
cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
|
||||||
|
val = __raw_readl(cfg_chip3_base);
|
||||||
|
|
||||||
|
if (soc_info->emac_pdata->rmii_en) {
|
||||||
|
val |= BIT(8);
|
||||||
|
ret = davinci_cfg_reg_list(mityomap_rmii_pins);
|
||||||
|
pr_info("RMII PHY configured\n");
|
||||||
|
} else {
|
||||||
|
val &= ~BIT(8);
|
||||||
|
ret = davinci_cfg_reg_list(mityomap_mii_pins);
|
||||||
|
pr_info("MII PHY configured\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
pr_warning("mii/rmii mux setup failed: %d\n", ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* configure the CFGCHIP3 register for RMII or MII */
|
||||||
|
__raw_writel(val, cfg_chip3_base);
|
||||||
|
|
||||||
|
soc_info->emac_pdata->phy_id = MITYOMAPL138_PHY_ID;
|
||||||
|
|
||||||
|
ret = da8xx_register_emac();
|
||||||
|
if (ret)
|
||||||
|
pr_warning("emac registration failed: %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct davinci_pm_config da850_pm_pdata = {
|
||||||
|
.sleepcount = 128,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device da850_pm_device = {
|
||||||
|
.name = "pm-davinci",
|
||||||
|
.dev = {
|
||||||
|
.platform_data = &da850_pm_pdata,
|
||||||
|
},
|
||||||
|
.id = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init mityomapl138_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* for now, no special EDMA channels are reserved */
|
||||||
|
ret = da850_register_edma(NULL);
|
||||||
|
if (ret)
|
||||||
|
pr_warning("edma registration failed: %d\n", ret);
|
||||||
|
|
||||||
|
ret = da8xx_register_watchdog();
|
||||||
|
if (ret)
|
||||||
|
pr_warning("watchdog registration failed: %d\n", ret);
|
||||||
|
|
||||||
|
davinci_serial_init(&mityomapl138_uart_config);
|
||||||
|
|
||||||
|
ret = da8xx_register_i2c(0, &mityomap_i2c_0_pdata);
|
||||||
|
if (ret)
|
||||||
|
pr_warning("i2c0 registration failed: %d\n", ret);
|
||||||
|
|
||||||
|
ret = pmic_tps65023_init();
|
||||||
|
if (ret)
|
||||||
|
pr_warning("TPS65023 PMIC init failed: %d\n", ret);
|
||||||
|
|
||||||
|
mityomapl138_setup_nand();
|
||||||
|
|
||||||
|
mityomapl138_config_emac();
|
||||||
|
|
||||||
|
ret = da8xx_register_rtc();
|
||||||
|
if (ret)
|
||||||
|
pr_warning("rtc setup failed: %d\n", ret);
|
||||||
|
|
||||||
|
ret = da850_register_cpufreq("pll0_sysclk3");
|
||||||
|
if (ret)
|
||||||
|
pr_warning("cpufreq registration failed: %d\n", ret);
|
||||||
|
|
||||||
|
ret = da8xx_register_cpuidle();
|
||||||
|
if (ret)
|
||||||
|
pr_warning("cpuidle registration failed: %d\n", ret);
|
||||||
|
|
||||||
|
ret = da850_register_pm(&da850_pm_device);
|
||||||
|
if (ret)
|
||||||
|
pr_warning("da850_evm_init: suspend registration failed: %d\n",
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||||
|
static int __init mityomapl138_console_init(void)
|
||||||
|
{
|
||||||
|
if (!machine_is_mityomapl138())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return add_preferred_console("ttyS", 1, "115200");
|
||||||
|
}
|
||||||
|
console_initcall(mityomapl138_console_init);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void __init mityomapl138_map_io(void)
|
||||||
|
{
|
||||||
|
da850_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
|
||||||
|
.phys_io = IO_PHYS,
|
||||||
|
.io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
|
||||||
|
.boot_params = (DA8XX_DDR_BASE + 0x100),
|
||||||
|
.map_io = mityomapl138_map_io,
|
||||||
|
.init_irq = cp_intc_init,
|
||||||
|
.timer = &davinci_timer,
|
||||||
|
.init_machine = mityomapl138_init,
|
||||||
|
MACHINE_END
|
|
@ -39,9 +39,7 @@
|
||||||
#include <mach/mmc.h>
|
#include <mach/mmc.h>
|
||||||
#include <mach/usb.h>
|
#include <mach/usb.h>
|
||||||
|
|
||||||
#define NEUROS_OSD2_PHY_MASK 0x2
|
#define NEUROS_OSD2_PHY_ID "0:01"
|
||||||
#define NEUROS_OSD2_MDIO_FREQUENCY 2200000 /* PHY bus frequency */
|
|
||||||
|
|
||||||
#define LXT971_PHY_ID 0x001378e2
|
#define LXT971_PHY_ID 0x001378e2
|
||||||
#define LXT971_PHY_MASK 0xfffffff0
|
#define LXT971_PHY_MASK 0xfffffff0
|
||||||
|
|
||||||
|
@ -252,8 +250,7 @@ static __init void davinci_ntosd2_init(void)
|
||||||
davinci_serial_init(&uart_config);
|
davinci_serial_init(&uart_config);
|
||||||
dm644x_init_asp(&dm644x_ntosd2_snd_data);
|
dm644x_init_asp(&dm644x_ntosd2_snd_data);
|
||||||
|
|
||||||
soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK;
|
soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID;
|
||||||
soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY;
|
|
||||||
|
|
||||||
davinci_setup_usb(1000, 8);
|
davinci_setup_usb(1000, 8);
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Hawkboard.org based on TI's OMAP-L138 Platform
|
||||||
|
*
|
||||||
|
* Initial code: Syed Mohammed Khasim
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com
|
||||||
|
*
|
||||||
|
* This file is licensed under the terms of the GNU General Public License
|
||||||
|
* version 2. This program is licensed "as is" without any warranty of
|
||||||
|
* any kind, whether express or implied.
|
||||||
|
*/
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/console.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
#include <asm/mach/arch.h>
|
||||||
|
|
||||||
|
#include <mach/cp_intc.h>
|
||||||
|
#include <mach/da8xx.h>
|
||||||
|
|
||||||
|
static struct davinci_uart_config omapl138_hawk_uart_config __initdata = {
|
||||||
|
.enabled_uarts = 0x7,
|
||||||
|
};
|
||||||
|
|
||||||
|
static __init void omapl138_hawk_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
davinci_serial_init(&omapl138_hawk_uart_config);
|
||||||
|
|
||||||
|
ret = da8xx_register_watchdog();
|
||||||
|
if (ret)
|
||||||
|
pr_warning("omapl138_hawk_init: "
|
||||||
|
"watchdog registration failed: %d\n",
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||||
|
static int __init omapl138_hawk_console_init(void)
|
||||||
|
{
|
||||||
|
if (!machine_is_omapl138_hawkboard())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return add_preferred_console("ttyS", 2, "115200");
|
||||||
|
}
|
||||||
|
console_initcall(omapl138_hawk_console_init);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void __init omapl138_hawk_map_io(void)
|
||||||
|
{
|
||||||
|
da850_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
|
||||||
|
.phys_io = IO_PHYS,
|
||||||
|
.io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
|
||||||
|
.boot_params = (DA8XX_DDR_BASE + 0x100),
|
||||||
|
.map_io = omapl138_hawk_map_io,
|
||||||
|
.init_irq = cp_intc_init,
|
||||||
|
.timer = &davinci_timer,
|
||||||
|
.init_machine = omapl138_hawk_init,
|
||||||
|
MACHINE_END
|
|
@ -42,9 +42,7 @@
|
||||||
#include <mach/mux.h>
|
#include <mach/mux.h>
|
||||||
#include <mach/usb.h>
|
#include <mach/usb.h>
|
||||||
|
|
||||||
#define SFFSDR_PHY_MASK (0x2)
|
#define SFFSDR_PHY_ID "0:01"
|
||||||
#define SFFSDR_MDIO_FREQUENCY (2200000) /* PHY bus frequency */
|
|
||||||
|
|
||||||
static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
|
static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
|
||||||
/* U-Boot Environment: Block 0
|
/* U-Boot Environment: Block 0
|
||||||
* UBL: Block 1
|
* UBL: Block 1
|
||||||
|
@ -143,8 +141,7 @@ static __init void davinci_sffsdr_init(void)
|
||||||
ARRAY_SIZE(davinci_sffsdr_devices));
|
ARRAY_SIZE(davinci_sffsdr_devices));
|
||||||
sffsdr_init_i2c();
|
sffsdr_init_i2c();
|
||||||
davinci_serial_init(&uart_config);
|
davinci_serial_init(&uart_config);
|
||||||
soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK;
|
soc_info->emac_pdata->phy_id = SFFSDR_PHY_ID;
|
||||||
soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY;
|
|
||||||
davinci_setup_usb(0, 0); /* We support only peripheral mode. */
|
davinci_setup_usb(0, 0); /* We support only peripheral mode. */
|
||||||
|
|
||||||
/* mux VLYNQ pins */
|
/* mux VLYNQ pins */
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/mtd/mtd.h>
|
#include <linux/mtd/mtd.h>
|
||||||
#include <linux/mtd/partitions.h>
|
#include <linux/mtd/partitions.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/input/matrix_keypad.h>
|
||||||
|
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
|
|
||||||
|
@ -141,10 +144,63 @@ static struct davinci_uart_config serial_config __initconst = {
|
||||||
.enabled_uarts = BIT(1),
|
.enabled_uarts = BIT(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint32_t keymap[] = {
|
||||||
|
KEY(0, 0, KEY_NUMERIC_1),
|
||||||
|
KEY(0, 1, KEY_NUMERIC_2),
|
||||||
|
KEY(0, 2, KEY_NUMERIC_3),
|
||||||
|
KEY(0, 3, KEY_FN_F1),
|
||||||
|
KEY(0, 4, KEY_MENU),
|
||||||
|
|
||||||
|
KEY(1, 0, KEY_NUMERIC_4),
|
||||||
|
KEY(1, 1, KEY_NUMERIC_5),
|
||||||
|
KEY(1, 2, KEY_NUMERIC_6),
|
||||||
|
KEY(1, 3, KEY_UP),
|
||||||
|
KEY(1, 4, KEY_FN_F2),
|
||||||
|
|
||||||
|
KEY(2, 0, KEY_NUMERIC_7),
|
||||||
|
KEY(2, 1, KEY_NUMERIC_8),
|
||||||
|
KEY(2, 2, KEY_NUMERIC_9),
|
||||||
|
KEY(2, 3, KEY_LEFT),
|
||||||
|
KEY(2, 4, KEY_ENTER),
|
||||||
|
|
||||||
|
KEY(3, 0, KEY_NUMERIC_STAR),
|
||||||
|
KEY(3, 1, KEY_NUMERIC_0),
|
||||||
|
KEY(3, 2, KEY_NUMERIC_POUND),
|
||||||
|
KEY(3, 3, KEY_DOWN),
|
||||||
|
KEY(3, 4, KEY_RIGHT),
|
||||||
|
|
||||||
|
KEY(4, 0, KEY_FN_F3),
|
||||||
|
KEY(4, 1, KEY_FN_F4),
|
||||||
|
KEY(4, 2, KEY_MUTE),
|
||||||
|
KEY(4, 3, KEY_HOME),
|
||||||
|
KEY(4, 4, KEY_BACK),
|
||||||
|
|
||||||
|
KEY(5, 0, KEY_VOLUMEDOWN),
|
||||||
|
KEY(5, 1, KEY_VOLUMEUP),
|
||||||
|
KEY(5, 2, KEY_F1),
|
||||||
|
KEY(5, 3, KEY_F2),
|
||||||
|
KEY(5, 4, KEY_F3),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct matrix_keymap_data keymap_data = {
|
||||||
|
.keymap = keymap,
|
||||||
|
.keymap_size = ARRAY_SIZE(keymap),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct matrix_keypad_platform_data keypad_config = {
|
||||||
|
.keymap_data = &keymap_data,
|
||||||
|
.num_row_gpios = 6,
|
||||||
|
.num_col_gpios = 5,
|
||||||
|
.debounce_ms = 0, /* minimum */
|
||||||
|
.active_low = 0, /* pull up realization */
|
||||||
|
.no_autorepeat = 0,
|
||||||
|
};
|
||||||
|
|
||||||
static struct tnetv107x_device_info evm_device_info __initconst = {
|
static struct tnetv107x_device_info evm_device_info __initconst = {
|
||||||
.serial_config = &serial_config,
|
.serial_config = &serial_config,
|
||||||
.mmc_config[1] = &mmc_config, /* controller 1 */
|
.mmc_config[1] = &mmc_config, /* controller 1 */
|
||||||
.nand_config[0] = &nand_config, /* chip select 0 */
|
.nand_config[0] = &nand_config, /* chip select 0 */
|
||||||
|
.keypad_config = &keypad_config,
|
||||||
};
|
};
|
||||||
|
|
||||||
static __init void tnetv107x_evm_board_init(void)
|
static __init void tnetv107x_evm_board_init(void)
|
||||||
|
|
|
@ -236,7 +236,7 @@ static int __init clk_disable_unused(void)
|
||||||
if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc))
|
if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pr_info("Clocks: disable unused %s\n", ck->name);
|
pr_debug("Clocks: disable unused %s\n", ck->name);
|
||||||
|
|
||||||
davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc,
|
davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc,
|
||||||
(ck->flags & PSC_SWRSTDISABLE) ?
|
(ck->flags & PSC_SWRSTDISABLE) ?
|
||||||
|
@ -287,6 +287,79 @@ static unsigned long clk_sysclk_recalc(struct clk *clk)
|
||||||
return rate;
|
return rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate)
|
||||||
|
{
|
||||||
|
unsigned v;
|
||||||
|
struct pll_data *pll;
|
||||||
|
unsigned long input;
|
||||||
|
unsigned ratio = 0;
|
||||||
|
|
||||||
|
/* If this is the PLL base clock, wrong function to call */
|
||||||
|
if (clk->pll_data)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* There must be a parent... */
|
||||||
|
if (WARN_ON(!clk->parent))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* ... the parent must be a PLL... */
|
||||||
|
if (WARN_ON(!clk->parent->pll_data))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* ... and this clock must have a divider. */
|
||||||
|
if (WARN_ON(!clk->div_reg))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pll = clk->parent->pll_data;
|
||||||
|
|
||||||
|
input = clk->parent->rate;
|
||||||
|
|
||||||
|
/* If pre-PLL, source clock is before the multiplier and divider(s) */
|
||||||
|
if (clk->flags & PRE_PLL)
|
||||||
|
input = pll->input_rate;
|
||||||
|
|
||||||
|
if (input > rate) {
|
||||||
|
/*
|
||||||
|
* Can afford to provide an output little higher than requested
|
||||||
|
* only if maximum rate supported by hardware on this sysclk
|
||||||
|
* is known.
|
||||||
|
*/
|
||||||
|
if (clk->maxrate) {
|
||||||
|
ratio = DIV_ROUND_CLOSEST(input, rate);
|
||||||
|
if (input / ratio > clk->maxrate)
|
||||||
|
ratio = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ratio == 0)
|
||||||
|
ratio = DIV_ROUND_UP(input, rate);
|
||||||
|
|
||||||
|
ratio--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ratio > PLLDIV_RATIO_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
v = __raw_readl(pll->base + PLLSTAT);
|
||||||
|
} while (v & PLLSTAT_GOSTAT);
|
||||||
|
|
||||||
|
v = __raw_readl(pll->base + clk->div_reg);
|
||||||
|
v &= ~PLLDIV_RATIO_MASK;
|
||||||
|
v |= ratio | PLLDIV_EN;
|
||||||
|
__raw_writel(v, pll->base + clk->div_reg);
|
||||||
|
|
||||||
|
v = __raw_readl(pll->base + PLLCMD);
|
||||||
|
v |= PLLCMD_GOSET;
|
||||||
|
__raw_writel(v, pll->base + PLLCMD);
|
||||||
|
|
||||||
|
do {
|
||||||
|
v = __raw_readl(pll->base + PLLSTAT);
|
||||||
|
} while (v & PLLSTAT_GOSTAT);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(davinci_set_sysclk_rate);
|
||||||
|
|
||||||
static unsigned long clk_leafclk_recalc(struct clk *clk)
|
static unsigned long clk_leafclk_recalc(struct clk *clk)
|
||||||
{
|
{
|
||||||
if (WARN_ON(!clk->parent))
|
if (WARN_ON(!clk->parent))
|
||||||
|
|
|
@ -70,6 +70,9 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <asm/clkdev.h>
|
#include <asm/clkdev.h>
|
||||||
|
|
||||||
|
#define PLLSTAT_GOSTAT BIT(0)
|
||||||
|
#define PLLCMD_GOSET BIT(0)
|
||||||
|
|
||||||
struct pll_data {
|
struct pll_data {
|
||||||
u32 phys_base;
|
u32 phys_base;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
@ -86,6 +89,7 @@ struct clk {
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned long rate;
|
unsigned long rate;
|
||||||
|
unsigned long maxrate; /* H/W supported max rate */
|
||||||
u8 usecount;
|
u8 usecount;
|
||||||
u8 lpsc;
|
u8 lpsc;
|
||||||
u8 gpsc;
|
u8 gpsc;
|
||||||
|
@ -118,6 +122,7 @@ struct clk {
|
||||||
int davinci_clk_init(struct clk_lookup *clocks);
|
int davinci_clk_init(struct clk_lookup *clocks);
|
||||||
int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
|
int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
|
||||||
unsigned int mult, unsigned int postdiv);
|
unsigned int mult, unsigned int postdiv);
|
||||||
|
int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate);
|
||||||
|
|
||||||
extern struct platform_device davinci_wdt_device;
|
extern struct platform_device davinci_wdt_device;
|
||||||
extern void davinci_watchdog_reset(struct platform_device *);
|
extern void davinci_watchdog_reset(struct platform_device *);
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
struct davinci_cpufreq {
|
struct davinci_cpufreq {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct clk *armclk;
|
struct clk *armclk;
|
||||||
|
struct clk *asyncclk;
|
||||||
|
unsigned long asyncrate;
|
||||||
};
|
};
|
||||||
static struct davinci_cpufreq cpufreq;
|
static struct davinci_cpufreq cpufreq;
|
||||||
|
|
||||||
|
@ -104,15 +106,27 @@ static int davinci_target(struct cpufreq_policy *policy,
|
||||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||||
|
|
||||||
/* if moving to higher frequency, up the voltage beforehand */
|
/* if moving to higher frequency, up the voltage beforehand */
|
||||||
if (pdata->set_voltage && freqs.new > freqs.old)
|
if (pdata->set_voltage && freqs.new > freqs.old) {
|
||||||
pdata->set_voltage(idx);
|
ret = pdata->set_voltage(idx);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = clk_set_rate(armclk, idx);
|
ret = clk_set_rate(armclk, idx);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (cpufreq.asyncclk) {
|
||||||
|
ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* if moving to lower freq, lower the voltage after lowering freq */
|
/* if moving to lower freq, lower the voltage after lowering freq */
|
||||||
if (pdata->set_voltage && freqs.new < freqs.old)
|
if (pdata->set_voltage && freqs.new < freqs.old)
|
||||||
pdata->set_voltage(idx);
|
pdata->set_voltage(idx);
|
||||||
|
|
||||||
|
out:
|
||||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -185,6 +199,7 @@ static struct cpufreq_driver davinci_driver = {
|
||||||
static int __init davinci_cpufreq_probe(struct platform_device *pdev)
|
static int __init davinci_cpufreq_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct davinci_cpufreq_config *pdata = pdev->dev.platform_data;
|
struct davinci_cpufreq_config *pdata = pdev->dev.platform_data;
|
||||||
|
struct clk *asyncclk;
|
||||||
|
|
||||||
if (!pdata)
|
if (!pdata)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -199,6 +214,12 @@ static int __init davinci_cpufreq_probe(struct platform_device *pdev)
|
||||||
return PTR_ERR(cpufreq.armclk);
|
return PTR_ERR(cpufreq.armclk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asyncclk = clk_get(cpufreq.dev, "async");
|
||||||
|
if (!IS_ERR(asyncclk)) {
|
||||||
|
cpufreq.asyncclk = asyncclk;
|
||||||
|
cpufreq.asyncrate = clk_get_rate(asyncclk);
|
||||||
|
}
|
||||||
|
|
||||||
return cpufreq_register_driver(&davinci_driver);
|
return cpufreq_register_driver(&davinci_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +227,9 @@ static int __exit davinci_cpufreq_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
clk_put(cpufreq.armclk);
|
clk_put(cpufreq.armclk);
|
||||||
|
|
||||||
|
if (cpufreq.asyncclk)
|
||||||
|
clk_put(cpufreq.asyncclk);
|
||||||
|
|
||||||
return cpufreq_unregister_driver(&davinci_driver);
|
return cpufreq_unregister_driver(&davinci_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,8 @@ static struct clk pll0_sysclk3 = {
|
||||||
.parent = &pll0_clk,
|
.parent = &pll0_clk,
|
||||||
.flags = CLK_PLL,
|
.flags = CLK_PLL,
|
||||||
.div_reg = PLLDIV3,
|
.div_reg = PLLDIV3,
|
||||||
|
.set_rate = davinci_set_sysclk_rate,
|
||||||
|
.maxrate = 100000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct clk pll0_sysclk4 = {
|
static struct clk pll0_sysclk4 = {
|
||||||
|
@ -323,12 +325,19 @@ static struct clk lcdc_clk = {
|
||||||
.gpsc = 1,
|
.gpsc = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct clk mmcsd_clk = {
|
static struct clk mmcsd0_clk = {
|
||||||
.name = "mmcsd",
|
.name = "mmcsd0",
|
||||||
.parent = &pll0_sysclk2,
|
.parent = &pll0_sysclk2,
|
||||||
.lpsc = DA8XX_LPSC0_MMC_SD,
|
.lpsc = DA8XX_LPSC0_MMC_SD,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct clk mmcsd1_clk = {
|
||||||
|
.name = "mmcsd1",
|
||||||
|
.parent = &pll0_sysclk2,
|
||||||
|
.lpsc = DA850_LPSC1_MMC_SD1,
|
||||||
|
.gpsc = 1,
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk aemif_clk = {
|
static struct clk aemif_clk = {
|
||||||
.name = "aemif",
|
.name = "aemif",
|
||||||
.parent = &pll0_sysclk3,
|
.parent = &pll0_sysclk3,
|
||||||
|
@ -375,7 +384,8 @@ static struct clk_lookup da850_clks[] = {
|
||||||
CLK("davinci_emac.1", NULL, &emac_clk),
|
CLK("davinci_emac.1", NULL, &emac_clk),
|
||||||
CLK("davinci-mcasp.0", NULL, &mcasp_clk),
|
CLK("davinci-mcasp.0", NULL, &mcasp_clk),
|
||||||
CLK("da8xx_lcdc.0", NULL, &lcdc_clk),
|
CLK("da8xx_lcdc.0", NULL, &lcdc_clk),
|
||||||
CLK("davinci_mmc.0", NULL, &mmcsd_clk),
|
CLK("davinci_mmc.0", NULL, &mmcsd0_clk),
|
||||||
|
CLK("davinci_mmc.1", NULL, &mmcsd1_clk),
|
||||||
CLK(NULL, "aemif", &aemif_clk),
|
CLK(NULL, "aemif", &aemif_clk),
|
||||||
CLK(NULL, NULL, NULL),
|
CLK(NULL, NULL, NULL),
|
||||||
};
|
};
|
||||||
|
@ -572,15 +582,9 @@ const short da850_cpgmac_pins[] __initdata = {
|
||||||
DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
|
DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
|
||||||
DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
|
DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
|
||||||
DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
|
DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
|
||||||
DA850_MDIO_D,
|
DA850_MDIO_D, DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
|
||||||
-1
|
DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, DA850_RMII_RXER,
|
||||||
};
|
DA850_RMII_MHZ_50_CLK,
|
||||||
|
|
||||||
const short da850_rmii_pins[] __initdata = {
|
|
||||||
DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
|
|
||||||
DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
|
|
||||||
DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
|
|
||||||
DA850_MDIO_D,
|
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -607,27 +611,19 @@ const short da850_mmcsd0_pins[] __initdata = {
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
const short da850_nand_pins[] __initdata = {
|
const short da850_emif25_pins[] __initdata = {
|
||||||
DA850_EMA_D_7, DA850_EMA_D_6, DA850_EMA_D_5, DA850_EMA_D_4,
|
|
||||||
DA850_EMA_D_3, DA850_EMA_D_2, DA850_EMA_D_1, DA850_EMA_D_0,
|
|
||||||
DA850_EMA_A_1, DA850_EMA_A_2, DA850_NEMA_CS_3, DA850_NEMA_CS_4,
|
|
||||||
DA850_NEMA_WE, DA850_NEMA_OE,
|
|
||||||
-1
|
|
||||||
};
|
|
||||||
|
|
||||||
const short da850_nor_pins[] __initdata = {
|
|
||||||
DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
|
DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
|
||||||
DA850_NEMA_WE, DA850_NEMA_OE, DA850_EMA_D_0, DA850_EMA_D_1,
|
DA850_NEMA_CS_3, DA850_NEMA_CS_4, DA850_NEMA_WE, DA850_NEMA_OE,
|
||||||
DA850_EMA_D_2, DA850_EMA_D_3, DA850_EMA_D_4, DA850_EMA_D_5,
|
DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
|
||||||
DA850_EMA_D_6, DA850_EMA_D_7, DA850_EMA_D_8, DA850_EMA_D_9,
|
DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
|
||||||
DA850_EMA_D_10, DA850_EMA_D_11, DA850_EMA_D_12, DA850_EMA_D_13,
|
DA850_EMA_D_8, DA850_EMA_D_9, DA850_EMA_D_10, DA850_EMA_D_11,
|
||||||
DA850_EMA_D_14, DA850_EMA_D_15, DA850_EMA_A_0, DA850_EMA_A_1,
|
DA850_EMA_D_12, DA850_EMA_D_13, DA850_EMA_D_14, DA850_EMA_D_15,
|
||||||
DA850_EMA_A_2, DA850_EMA_A_3, DA850_EMA_A_4, DA850_EMA_A_5,
|
DA850_EMA_A_0, DA850_EMA_A_1, DA850_EMA_A_2, DA850_EMA_A_3,
|
||||||
DA850_EMA_A_6, DA850_EMA_A_7, DA850_EMA_A_8, DA850_EMA_A_9,
|
DA850_EMA_A_4, DA850_EMA_A_5, DA850_EMA_A_6, DA850_EMA_A_7,
|
||||||
DA850_EMA_A_10, DA850_EMA_A_11, DA850_EMA_A_12, DA850_EMA_A_13,
|
DA850_EMA_A_8, DA850_EMA_A_9, DA850_EMA_A_10, DA850_EMA_A_11,
|
||||||
DA850_EMA_A_14, DA850_EMA_A_15, DA850_EMA_A_16, DA850_EMA_A_17,
|
DA850_EMA_A_12, DA850_EMA_A_13, DA850_EMA_A_14, DA850_EMA_A_15,
|
||||||
DA850_EMA_A_18, DA850_EMA_A_19, DA850_EMA_A_20, DA850_EMA_A_21,
|
DA850_EMA_A_16, DA850_EMA_A_17, DA850_EMA_A_18, DA850_EMA_A_19,
|
||||||
DA850_EMA_A_22, DA850_EMA_A_23,
|
DA850_EMA_A_20, DA850_EMA_A_21, DA850_EMA_A_22, DA850_EMA_A_23,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -851,7 +847,7 @@ static const struct da850_opp da850_opp_300 = {
|
||||||
.prediv = 1,
|
.prediv = 1,
|
||||||
.mult = 25,
|
.mult = 25,
|
||||||
.postdiv = 2,
|
.postdiv = 2,
|
||||||
.cvdd_min = 1140000,
|
.cvdd_min = 1200000,
|
||||||
.cvdd_max = 1320000,
|
.cvdd_max = 1320000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -860,7 +856,7 @@ static const struct da850_opp da850_opp_200 = {
|
||||||
.prediv = 1,
|
.prediv = 1,
|
||||||
.mult = 25,
|
.mult = 25,
|
||||||
.postdiv = 3,
|
.postdiv = 3,
|
||||||
.cvdd_min = 1050000,
|
.cvdd_min = 1100000,
|
||||||
.cvdd_max = 1160000,
|
.cvdd_max = 1160000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -869,7 +865,7 @@ static const struct da850_opp da850_opp_96 = {
|
||||||
.prediv = 1,
|
.prediv = 1,
|
||||||
.mult = 20,
|
.mult = 20,
|
||||||
.postdiv = 5,
|
.postdiv = 5,
|
||||||
.cvdd_min = 950000,
|
.cvdd_min = 1000000,
|
||||||
.cvdd_max = 1050000,
|
.cvdd_max = 1050000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -929,10 +925,16 @@ static struct platform_device da850_cpufreq_device = {
|
||||||
.dev = {
|
.dev = {
|
||||||
.platform_data = &cpufreq_info,
|
.platform_data = &cpufreq_info,
|
||||||
},
|
},
|
||||||
|
.id = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
int __init da850_register_cpufreq(void)
|
int __init da850_register_cpufreq(char *async_clk)
|
||||||
{
|
{
|
||||||
|
/* cpufreq driver can help keep an "async" clock constant */
|
||||||
|
if (async_clk)
|
||||||
|
clk_add_alias("async", da850_cpufreq_device.name,
|
||||||
|
async_clk, NULL);
|
||||||
|
|
||||||
return platform_device_register(&da850_cpufreq_device);
|
return platform_device_register(&da850_cpufreq_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -983,7 +985,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int __init da850_register_cpufreq(void)
|
int __init da850_register_cpufreq(char *async_clk)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
|
||||||
#define DA8XX_TPCC_BASE 0x01c00000
|
#define DA8XX_TPCC_BASE 0x01c00000
|
||||||
|
#define DA850_MMCSD1_BASE 0x01e1b000
|
||||||
#define DA850_TPCC1_BASE 0x01e30000
|
#define DA850_TPCC1_BASE 0x01e30000
|
||||||
#define DA8XX_TPTC0_BASE 0x01c08000
|
#define DA8XX_TPTC0_BASE 0x01c08000
|
||||||
#define DA8XX_TPTC1_BASE 0x01c08400
|
#define DA8XX_TPTC1_BASE 0x01c08400
|
||||||
|
@ -41,7 +42,6 @@
|
||||||
#define DA8XX_EMAC_CTRL_REG_OFFSET 0x3000
|
#define DA8XX_EMAC_CTRL_REG_OFFSET 0x3000
|
||||||
#define DA8XX_EMAC_MOD_REG_OFFSET 0x2000
|
#define DA8XX_EMAC_MOD_REG_OFFSET 0x2000
|
||||||
#define DA8XX_EMAC_RAM_OFFSET 0x0000
|
#define DA8XX_EMAC_RAM_OFFSET 0x0000
|
||||||
#define DA8XX_MDIO_REG_OFFSET 0x4000
|
|
||||||
#define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K
|
#define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K
|
||||||
|
|
||||||
void __iomem *da8xx_syscfg0_base;
|
void __iomem *da8xx_syscfg0_base;
|
||||||
|
@ -351,7 +351,7 @@ int __init da8xx_register_watchdog(void)
|
||||||
static struct resource da8xx_emac_resources[] = {
|
static struct resource da8xx_emac_resources[] = {
|
||||||
{
|
{
|
||||||
.start = DA8XX_EMAC_CPPI_PORT_BASE,
|
.start = DA8XX_EMAC_CPPI_PORT_BASE,
|
||||||
.end = DA8XX_EMAC_CPPI_PORT_BASE + 0x5000 - 1,
|
.end = DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1,
|
||||||
.flags = IORESOURCE_MEM,
|
.flags = IORESOURCE_MEM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -380,7 +380,6 @@ struct emac_platform_data da8xx_emac_pdata = {
|
||||||
.ctrl_reg_offset = DA8XX_EMAC_CTRL_REG_OFFSET,
|
.ctrl_reg_offset = DA8XX_EMAC_CTRL_REG_OFFSET,
|
||||||
.ctrl_mod_reg_offset = DA8XX_EMAC_MOD_REG_OFFSET,
|
.ctrl_mod_reg_offset = DA8XX_EMAC_MOD_REG_OFFSET,
|
||||||
.ctrl_ram_offset = DA8XX_EMAC_RAM_OFFSET,
|
.ctrl_ram_offset = DA8XX_EMAC_RAM_OFFSET,
|
||||||
.mdio_reg_offset = DA8XX_MDIO_REG_OFFSET,
|
|
||||||
.ctrl_ram_size = DA8XX_EMAC_CTRL_RAM_SIZE,
|
.ctrl_ram_size = DA8XX_EMAC_CTRL_RAM_SIZE,
|
||||||
.version = EMAC_VERSION_2,
|
.version = EMAC_VERSION_2,
|
||||||
};
|
};
|
||||||
|
@ -395,9 +394,34 @@ static struct platform_device da8xx_emac_device = {
|
||||||
.resource = da8xx_emac_resources,
|
.resource = da8xx_emac_resources,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct resource da8xx_mdio_resources[] = {
|
||||||
|
{
|
||||||
|
.start = DA8XX_EMAC_MDIO_BASE,
|
||||||
|
.end = DA8XX_EMAC_MDIO_BASE + SZ_4K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device da8xx_mdio_device = {
|
||||||
|
.name = "davinci_mdio",
|
||||||
|
.id = 0,
|
||||||
|
.num_resources = ARRAY_SIZE(da8xx_mdio_resources),
|
||||||
|
.resource = da8xx_mdio_resources,
|
||||||
|
};
|
||||||
|
|
||||||
int __init da8xx_register_emac(void)
|
int __init da8xx_register_emac(void)
|
||||||
{
|
{
|
||||||
return platform_device_register(&da8xx_emac_device);
|
int ret;
|
||||||
|
|
||||||
|
ret = platform_device_register(&da8xx_mdio_device);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
ret = platform_device_register(&da8xx_emac_device);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev),
|
||||||
|
NULL, &da8xx_emac_device.dev);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct resource da830_mcasp1_resources[] = {
|
static struct resource da830_mcasp1_resources[] = {
|
||||||
|
@ -566,6 +590,44 @@ int __init da8xx_register_mmcsd0(struct davinci_mmc_config *config)
|
||||||
return platform_device_register(&da8xx_mmcsd0_device);
|
return platform_device_register(&da8xx_mmcsd0_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_DAVINCI_DA850
|
||||||
|
static struct resource da850_mmcsd1_resources[] = {
|
||||||
|
{ /* registers */
|
||||||
|
.start = DA850_MMCSD1_BASE,
|
||||||
|
.end = DA850_MMCSD1_BASE + SZ_4K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
{ /* interrupt */
|
||||||
|
.start = IRQ_DA850_MMCSDINT0_1,
|
||||||
|
.end = IRQ_DA850_MMCSDINT0_1,
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
},
|
||||||
|
{ /* DMA RX */
|
||||||
|
.start = EDMA_CTLR_CHAN(1, 28),
|
||||||
|
.end = EDMA_CTLR_CHAN(1, 28),
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
{ /* DMA TX */
|
||||||
|
.start = EDMA_CTLR_CHAN(1, 29),
|
||||||
|
.end = EDMA_CTLR_CHAN(1, 29),
|
||||||
|
.flags = IORESOURCE_DMA,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device da850_mmcsd1_device = {
|
||||||
|
.name = "davinci_mmc",
|
||||||
|
.id = 1,
|
||||||
|
.num_resources = ARRAY_SIZE(da850_mmcsd1_resources),
|
||||||
|
.resource = da850_mmcsd1_resources,
|
||||||
|
};
|
||||||
|
|
||||||
|
int __init da850_register_mmcsd1(struct davinci_mmc_config *config)
|
||||||
|
{
|
||||||
|
da850_mmcsd1_device.dev.platform_data = config;
|
||||||
|
return platform_device_register(&da850_mmcsd1_device);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct resource da8xx_rtc_resources[] = {
|
static struct resource da8xx_rtc_resources[] = {
|
||||||
{
|
{
|
||||||
.start = DA8XX_RTC_BASE,
|
.start = DA8XX_RTC_BASE,
|
||||||
|
|
|
@ -31,8 +31,10 @@
|
||||||
#define TNETV107X_TPTC0_BASE 0x01c10000
|
#define TNETV107X_TPTC0_BASE 0x01c10000
|
||||||
#define TNETV107X_TPTC1_BASE 0x01c10400
|
#define TNETV107X_TPTC1_BASE 0x01c10400
|
||||||
#define TNETV107X_WDOG_BASE 0x08086700
|
#define TNETV107X_WDOG_BASE 0x08086700
|
||||||
|
#define TNETV107X_TSC_BASE 0x08088500
|
||||||
#define TNETV107X_SDIO0_BASE 0x08088700
|
#define TNETV107X_SDIO0_BASE 0x08088700
|
||||||
#define TNETV107X_SDIO1_BASE 0x08088800
|
#define TNETV107X_SDIO1_BASE 0x08088800
|
||||||
|
#define TNETV107X_KEYPAD_BASE 0x08088a00
|
||||||
#define TNETV107X_ASYNC_EMIF_CNTRL_BASE 0x08200000
|
#define TNETV107X_ASYNC_EMIF_CNTRL_BASE 0x08200000
|
||||||
#define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE 0x30000000
|
#define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE 0x30000000
|
||||||
#define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE 0x40000000
|
#define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE 0x40000000
|
||||||
|
@ -298,12 +300,55 @@ static int __init nand_init(int chipsel, struct davinci_nand_pdata *data)
|
||||||
return platform_device_register(pdev);
|
return platform_device_register(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct resource keypad_resources[] = {
|
||||||
|
{
|
||||||
|
.start = TNETV107X_KEYPAD_BASE,
|
||||||
|
.end = TNETV107X_KEYPAD_BASE + 0xff,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.start = IRQ_TNETV107X_KEYPAD,
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
.name = "press",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.start = IRQ_TNETV107X_KEYPAD_FREE,
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
.name = "release",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device keypad_device = {
|
||||||
|
.name = "tnetv107x-keypad",
|
||||||
|
.num_resources = ARRAY_SIZE(keypad_resources),
|
||||||
|
.resource = keypad_resources,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct resource tsc_resources[] = {
|
||||||
|
{
|
||||||
|
.start = TNETV107X_TSC_BASE,
|
||||||
|
.end = TNETV107X_TSC_BASE + 0xff,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.start = IRQ_TNETV107X_TSC,
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device tsc_device = {
|
||||||
|
.name = "tnetv107x-ts",
|
||||||
|
.num_resources = ARRAY_SIZE(tsc_resources),
|
||||||
|
.resource = tsc_resources,
|
||||||
|
};
|
||||||
|
|
||||||
void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
|
void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
platform_device_register(&edma_device);
|
platform_device_register(&edma_device);
|
||||||
platform_device_register(&tnetv107x_wdt_device);
|
platform_device_register(&tnetv107x_wdt_device);
|
||||||
|
platform_device_register(&tsc_device);
|
||||||
|
|
||||||
if (info->serial_config)
|
if (info->serial_config)
|
||||||
davinci_serial_init(info->serial_config);
|
davinci_serial_init(info->serial_config);
|
||||||
|
@ -317,4 +362,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
if (info->nand_config[i])
|
if (info->nand_config[i])
|
||||||
nand_init(i, info->nand_config[i]);
|
nand_init(i, info->nand_config[i]);
|
||||||
|
|
||||||
|
if (info->keypad_config) {
|
||||||
|
keypad_device.dev.platform_data = info->keypad_config;
|
||||||
|
platform_device_register(&keypad_device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,7 @@ void __init davinci_setup_mmc(int module, struct davinci_mmc_config *config)
|
||||||
IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + 0x7c);
|
IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + 0x7c);
|
||||||
|
|
||||||
/* Configure pull down control */
|
/* Configure pull down control */
|
||||||
__raw_writel((__raw_readl(pupdctl1) & ~0x400),
|
__raw_writel((__raw_readl(pupdctl1) & ~0xfc0),
|
||||||
pupdctl1);
|
pupdctl1);
|
||||||
|
|
||||||
mmcsd1_resources[0].start = DM365_MMCSD1_BASE;
|
mmcsd1_resources[0].start = DM365_MMCSD1_BASE;
|
||||||
|
|
|
@ -691,7 +691,6 @@ static struct emac_platform_data dm365_emac_pdata = {
|
||||||
.ctrl_reg_offset = DM365_EMAC_CNTRL_OFFSET,
|
.ctrl_reg_offset = DM365_EMAC_CNTRL_OFFSET,
|
||||||
.ctrl_mod_reg_offset = DM365_EMAC_CNTRL_MOD_OFFSET,
|
.ctrl_mod_reg_offset = DM365_EMAC_CNTRL_MOD_OFFSET,
|
||||||
.ctrl_ram_offset = DM365_EMAC_CNTRL_RAM_OFFSET,
|
.ctrl_ram_offset = DM365_EMAC_CNTRL_RAM_OFFSET,
|
||||||
.mdio_reg_offset = DM365_EMAC_MDIO_OFFSET,
|
|
||||||
.ctrl_ram_size = DM365_EMAC_CNTRL_RAM_SIZE,
|
.ctrl_ram_size = DM365_EMAC_CNTRL_RAM_SIZE,
|
||||||
.version = EMAC_VERSION_2,
|
.version = EMAC_VERSION_2,
|
||||||
};
|
};
|
||||||
|
@ -699,7 +698,7 @@ static struct emac_platform_data dm365_emac_pdata = {
|
||||||
static struct resource dm365_emac_resources[] = {
|
static struct resource dm365_emac_resources[] = {
|
||||||
{
|
{
|
||||||
.start = DM365_EMAC_BASE,
|
.start = DM365_EMAC_BASE,
|
||||||
.end = DM365_EMAC_BASE + 0x47ff,
|
.end = DM365_EMAC_BASE + SZ_16K - 1,
|
||||||
.flags = IORESOURCE_MEM,
|
.flags = IORESOURCE_MEM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -734,6 +733,21 @@ static struct platform_device dm365_emac_device = {
|
||||||
.resource = dm365_emac_resources,
|
.resource = dm365_emac_resources,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct resource dm365_mdio_resources[] = {
|
||||||
|
{
|
||||||
|
.start = DM365_EMAC_MDIO_BASE,
|
||||||
|
.end = DM365_EMAC_MDIO_BASE + SZ_4K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device dm365_mdio_device = {
|
||||||
|
.name = "davinci_mdio",
|
||||||
|
.id = 0,
|
||||||
|
.num_resources = ARRAY_SIZE(dm365_mdio_resources),
|
||||||
|
.resource = dm365_mdio_resources,
|
||||||
|
};
|
||||||
|
|
||||||
static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
|
static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
|
||||||
[IRQ_VDINT0] = 2,
|
[IRQ_VDINT0] = 2,
|
||||||
[IRQ_VDINT1] = 6,
|
[IRQ_VDINT1] = 6,
|
||||||
|
@ -1219,7 +1233,12 @@ static int __init dm365_init_devices(void)
|
||||||
|
|
||||||
davinci_cfg_reg(DM365_INT_EDMA_CC);
|
davinci_cfg_reg(DM365_INT_EDMA_CC);
|
||||||
platform_device_register(&dm365_edma_device);
|
platform_device_register(&dm365_edma_device);
|
||||||
|
|
||||||
|
platform_device_register(&dm365_mdio_device);
|
||||||
platform_device_register(&dm365_emac_device);
|
platform_device_register(&dm365_emac_device);
|
||||||
|
clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev),
|
||||||
|
NULL, &dm365_emac_device.dev);
|
||||||
|
|
||||||
/* Add isif clock alias */
|
/* Add isif clock alias */
|
||||||
clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL);
|
clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL);
|
||||||
platform_device_register(&dm365_vpss_device);
|
platform_device_register(&dm365_vpss_device);
|
||||||
|
|
|
@ -322,7 +322,6 @@ static struct emac_platform_data dm644x_emac_pdata = {
|
||||||
.ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET,
|
.ctrl_reg_offset = DM644X_EMAC_CNTRL_OFFSET,
|
||||||
.ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET,
|
.ctrl_mod_reg_offset = DM644X_EMAC_CNTRL_MOD_OFFSET,
|
||||||
.ctrl_ram_offset = DM644X_EMAC_CNTRL_RAM_OFFSET,
|
.ctrl_ram_offset = DM644X_EMAC_CNTRL_RAM_OFFSET,
|
||||||
.mdio_reg_offset = DM644X_EMAC_MDIO_OFFSET,
|
|
||||||
.ctrl_ram_size = DM644X_EMAC_CNTRL_RAM_SIZE,
|
.ctrl_ram_size = DM644X_EMAC_CNTRL_RAM_SIZE,
|
||||||
.version = EMAC_VERSION_1,
|
.version = EMAC_VERSION_1,
|
||||||
};
|
};
|
||||||
|
@ -330,7 +329,7 @@ static struct emac_platform_data dm644x_emac_pdata = {
|
||||||
static struct resource dm644x_emac_resources[] = {
|
static struct resource dm644x_emac_resources[] = {
|
||||||
{
|
{
|
||||||
.start = DM644X_EMAC_BASE,
|
.start = DM644X_EMAC_BASE,
|
||||||
.end = DM644X_EMAC_BASE + 0x47ff,
|
.end = DM644X_EMAC_BASE + SZ_16K - 1,
|
||||||
.flags = IORESOURCE_MEM,
|
.flags = IORESOURCE_MEM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -350,6 +349,21 @@ static struct platform_device dm644x_emac_device = {
|
||||||
.resource = dm644x_emac_resources,
|
.resource = dm644x_emac_resources,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct resource dm644x_mdio_resources[] = {
|
||||||
|
{
|
||||||
|
.start = DM644X_EMAC_MDIO_BASE,
|
||||||
|
.end = DM644X_EMAC_MDIO_BASE + SZ_4K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device dm644x_mdio_device = {
|
||||||
|
.name = "davinci_mdio",
|
||||||
|
.id = 0,
|
||||||
|
.num_resources = ARRAY_SIZE(dm644x_mdio_resources),
|
||||||
|
.resource = dm644x_mdio_resources,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Device specific mux setup
|
* Device specific mux setup
|
||||||
*
|
*
|
||||||
|
@ -776,7 +790,12 @@ static int __init dm644x_init_devices(void)
|
||||||
clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL);
|
clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL);
|
||||||
clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL);
|
clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL);
|
||||||
platform_device_register(&dm644x_edma_device);
|
platform_device_register(&dm644x_edma_device);
|
||||||
|
|
||||||
|
platform_device_register(&dm644x_mdio_device);
|
||||||
platform_device_register(&dm644x_emac_device);
|
platform_device_register(&dm644x_emac_device);
|
||||||
|
clk_add_alias(NULL, dev_name(&dm644x_mdio_device.dev),
|
||||||
|
NULL, &dm644x_emac_device.dev);
|
||||||
|
|
||||||
platform_device_register(&dm644x_vpss_device);
|
platform_device_register(&dm644x_vpss_device);
|
||||||
platform_device_register(&dm644x_ccdc_dev);
|
platform_device_register(&dm644x_ccdc_dev);
|
||||||
platform_device_register(&vpfe_capture_dev);
|
platform_device_register(&vpfe_capture_dev);
|
||||||
|
|
|
@ -358,7 +358,6 @@ static struct emac_platform_data dm646x_emac_pdata = {
|
||||||
.ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET,
|
.ctrl_reg_offset = DM646X_EMAC_CNTRL_OFFSET,
|
||||||
.ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET,
|
.ctrl_mod_reg_offset = DM646X_EMAC_CNTRL_MOD_OFFSET,
|
||||||
.ctrl_ram_offset = DM646X_EMAC_CNTRL_RAM_OFFSET,
|
.ctrl_ram_offset = DM646X_EMAC_CNTRL_RAM_OFFSET,
|
||||||
.mdio_reg_offset = DM646X_EMAC_MDIO_OFFSET,
|
|
||||||
.ctrl_ram_size = DM646X_EMAC_CNTRL_RAM_SIZE,
|
.ctrl_ram_size = DM646X_EMAC_CNTRL_RAM_SIZE,
|
||||||
.version = EMAC_VERSION_2,
|
.version = EMAC_VERSION_2,
|
||||||
};
|
};
|
||||||
|
@ -366,7 +365,7 @@ static struct emac_platform_data dm646x_emac_pdata = {
|
||||||
static struct resource dm646x_emac_resources[] = {
|
static struct resource dm646x_emac_resources[] = {
|
||||||
{
|
{
|
||||||
.start = DM646X_EMAC_BASE,
|
.start = DM646X_EMAC_BASE,
|
||||||
.end = DM646X_EMAC_BASE + 0x47ff,
|
.end = DM646X_EMAC_BASE + SZ_16K - 1,
|
||||||
.flags = IORESOURCE_MEM,
|
.flags = IORESOURCE_MEM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -401,6 +400,21 @@ static struct platform_device dm646x_emac_device = {
|
||||||
.resource = dm646x_emac_resources,
|
.resource = dm646x_emac_resources,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct resource dm646x_mdio_resources[] = {
|
||||||
|
{
|
||||||
|
.start = DM646X_EMAC_MDIO_BASE,
|
||||||
|
.end = DM646X_EMAC_MDIO_BASE + SZ_4K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device dm646x_mdio_device = {
|
||||||
|
.name = "davinci_mdio",
|
||||||
|
.id = 0,
|
||||||
|
.num_resources = ARRAY_SIZE(dm646x_mdio_resources),
|
||||||
|
.resource = dm646x_mdio_resources,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Device specific mux setup
|
* Device specific mux setup
|
||||||
*
|
*
|
||||||
|
@ -896,7 +910,11 @@ static int __init dm646x_init_devices(void)
|
||||||
if (!cpu_is_davinci_dm646x())
|
if (!cpu_is_davinci_dm646x())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
platform_device_register(&dm646x_mdio_device);
|
||||||
platform_device_register(&dm646x_emac_device);
|
platform_device_register(&dm646x_emac_device);
|
||||||
|
clk_add_alias(NULL, dev_name(&dm646x_mdio_device.dev),
|
||||||
|
NULL, &dm646x_emac_device.dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
postcore_initcall(dm646x_init_devices);
|
postcore_initcall(dm646x_init_devices);
|
||||||
|
|
|
@ -354,10 +354,12 @@ static int irq2ctlr(int irq)
|
||||||
static irqreturn_t dma_irq_handler(int irq, void *data)
|
static irqreturn_t dma_irq_handler(int irq, void *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned ctlr;
|
int ctlr;
|
||||||
unsigned int cnt = 0;
|
unsigned int cnt = 0;
|
||||||
|
|
||||||
ctlr = irq2ctlr(irq);
|
ctlr = irq2ctlr(irq);
|
||||||
|
if (ctlr < 0)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
dev_dbg(data, "dma_irq_handler\n");
|
dev_dbg(data, "dma_irq_handler\n");
|
||||||
|
|
||||||
|
@ -408,10 +410,12 @@ static irqreturn_t dma_irq_handler(int irq, void *data)
|
||||||
static irqreturn_t dma_ccerr_handler(int irq, void *data)
|
static irqreturn_t dma_ccerr_handler(int irq, void *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned ctlr;
|
int ctlr;
|
||||||
unsigned int cnt = 0;
|
unsigned int cnt = 0;
|
||||||
|
|
||||||
ctlr = irq2ctlr(irq);
|
ctlr = irq2ctlr(irq);
|
||||||
|
if (ctlr < 0)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
dev_dbg(data, "dma_ccerr_handler\n");
|
dev_dbg(data, "dma_ccerr_handler\n");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* TI DaVinci AEMIF support
|
||||||
|
*
|
||||||
|
* Copyright 2010 (C) Texas Instruments, Inc. http://www.ti.com/
|
||||||
|
*
|
||||||
|
* This file is licensed under the terms of the GNU General Public License
|
||||||
|
* version 2. This program is licensed "as is" without any warranty of any
|
||||||
|
* kind, whether express or implied.
|
||||||
|
*/
|
||||||
|
#ifndef _MACH_DAVINCI_AEMIF_H
|
||||||
|
#define _MACH_DAVINCI_AEMIF_H
|
||||||
|
|
||||||
|
#define NRCSR_OFFSET 0x00
|
||||||
|
#define AWCCR_OFFSET 0x04
|
||||||
|
#define A1CR_OFFSET 0x10
|
||||||
|
|
||||||
|
#define ACR_ASIZE_MASK 0x3
|
||||||
|
#define ACR_EW_MASK BIT(30)
|
||||||
|
#define ACR_SS_MASK BIT(31)
|
||||||
|
|
||||||
|
/* All timings in nanoseconds */
|
||||||
|
struct davinci_aemif_timing {
|
||||||
|
u8 wsetup;
|
||||||
|
u8 wstrobe;
|
||||||
|
u8 whold;
|
||||||
|
|
||||||
|
u8 rsetup;
|
||||||
|
u8 rstrobe;
|
||||||
|
u8 rhold;
|
||||||
|
|
||||||
|
u8 ta;
|
||||||
|
};
|
||||||
|
|
||||||
|
int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
|
||||||
|
void __iomem *base, unsigned cs);
|
||||||
|
#endif
|
|
@ -76,9 +76,10 @@ int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
|
||||||
int da8xx_register_emac(void);
|
int da8xx_register_emac(void);
|
||||||
int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
|
int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
|
||||||
int da8xx_register_mmcsd0(struct davinci_mmc_config *config);
|
int da8xx_register_mmcsd0(struct davinci_mmc_config *config);
|
||||||
|
int da850_register_mmcsd1(struct davinci_mmc_config *config);
|
||||||
void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata);
|
void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata);
|
||||||
int da8xx_register_rtc(void);
|
int da8xx_register_rtc(void);
|
||||||
int da850_register_cpufreq(void);
|
int da850_register_cpufreq(char *async_clk);
|
||||||
int da8xx_register_cpuidle(void);
|
int da8xx_register_cpuidle(void);
|
||||||
void __iomem * __init da8xx_get_mem_ctlr(void);
|
void __iomem * __init da8xx_get_mem_ctlr(void);
|
||||||
int da850_register_pm(struct platform_device *pdev);
|
int da850_register_pm(struct platform_device *pdev);
|
||||||
|
@ -121,11 +122,9 @@ extern const short da850_uart2_pins[];
|
||||||
extern const short da850_i2c0_pins[];
|
extern const short da850_i2c0_pins[];
|
||||||
extern const short da850_i2c1_pins[];
|
extern const short da850_i2c1_pins[];
|
||||||
extern const short da850_cpgmac_pins[];
|
extern const short da850_cpgmac_pins[];
|
||||||
extern const short da850_rmii_pins[];
|
|
||||||
extern const short da850_mcasp_pins[];
|
extern const short da850_mcasp_pins[];
|
||||||
extern const short da850_lcdcntl_pins[];
|
extern const short da850_lcdcntl_pins[];
|
||||||
extern const short da850_mmcsd0_pins[];
|
extern const short da850_mmcsd0_pins[];
|
||||||
extern const short da850_nand_pins[];
|
extern const short da850_emif25_pins[];
|
||||||
extern const short da850_nor_pins[];
|
|
||||||
|
|
||||||
#endif /* __ASM_ARCH_DAVINCI_DA8XX_H */
|
#endif /* __ASM_ARCH_DAVINCI_DA8XX_H */
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
#include <media/davinci/vpfe_capture.h>
|
#include <media/davinci/vpfe_capture.h>
|
||||||
|
|
||||||
#define DM365_EMAC_BASE (0x01D07000)
|
#define DM365_EMAC_BASE (0x01D07000)
|
||||||
|
#define DM365_EMAC_MDIO_BASE (DM365_EMAC_BASE + 0x4000)
|
||||||
#define DM365_EMAC_CNTRL_OFFSET (0x0000)
|
#define DM365_EMAC_CNTRL_OFFSET (0x0000)
|
||||||
#define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000)
|
#define DM365_EMAC_CNTRL_MOD_OFFSET (0x3000)
|
||||||
#define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000)
|
#define DM365_EMAC_CNTRL_RAM_OFFSET (0x1000)
|
||||||
#define DM365_EMAC_MDIO_OFFSET (0x4000)
|
|
||||||
#define DM365_EMAC_CNTRL_RAM_SIZE (0x2000)
|
#define DM365_EMAC_CNTRL_RAM_SIZE (0x2000)
|
||||||
|
|
||||||
/* Base of key scan register bank */
|
/* Base of key scan register bank */
|
||||||
|
|
|
@ -28,10 +28,10 @@
|
||||||
#include <media/davinci/vpfe_capture.h>
|
#include <media/davinci/vpfe_capture.h>
|
||||||
|
|
||||||
#define DM644X_EMAC_BASE (0x01C80000)
|
#define DM644X_EMAC_BASE (0x01C80000)
|
||||||
|
#define DM644X_EMAC_MDIO_BASE (DM644X_EMAC_BASE + 0x4000)
|
||||||
#define DM644X_EMAC_CNTRL_OFFSET (0x0000)
|
#define DM644X_EMAC_CNTRL_OFFSET (0x0000)
|
||||||
#define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000)
|
#define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000)
|
||||||
#define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000)
|
#define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000)
|
||||||
#define DM644X_EMAC_MDIO_OFFSET (0x4000)
|
|
||||||
#define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000)
|
#define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000)
|
||||||
|
|
||||||
#define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000
|
#define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
#include <linux/davinci_emac.h>
|
#include <linux/davinci_emac.h>
|
||||||
|
|
||||||
#define DM646X_EMAC_BASE (0x01C80000)
|
#define DM646X_EMAC_BASE (0x01C80000)
|
||||||
|
#define DM646X_EMAC_MDIO_BASE (DM646X_EMAC_BASE + 0x4000)
|
||||||
#define DM646X_EMAC_CNTRL_OFFSET (0x0000)
|
#define DM646X_EMAC_CNTRL_OFFSET (0x0000)
|
||||||
#define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000)
|
#define DM646X_EMAC_CNTRL_MOD_OFFSET (0x1000)
|
||||||
#define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000)
|
#define DM646X_EMAC_CNTRL_RAM_OFFSET (0x2000)
|
||||||
#define DM646X_EMAC_MDIO_OFFSET (0x4000)
|
|
||||||
#define DM646X_EMAC_CNTRL_RAM_SIZE (0x2000)
|
#define DM646X_EMAC_CNTRL_RAM_SIZE (0x2000)
|
||||||
|
|
||||||
#define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000
|
#define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000
|
||||||
|
|
|
@ -30,9 +30,6 @@
|
||||||
|
|
||||||
#include <linux/mtd/nand.h>
|
#include <linux/mtd/nand.h>
|
||||||
|
|
||||||
#define NRCSR_OFFSET 0x00
|
|
||||||
#define AWCCR_OFFSET 0x04
|
|
||||||
#define A1CR_OFFSET 0x10
|
|
||||||
#define NANDFCR_OFFSET 0x60
|
#define NANDFCR_OFFSET 0x60
|
||||||
#define NANDFSR_OFFSET 0x64
|
#define NANDFSR_OFFSET 0x64
|
||||||
#define NANDF1ECC_OFFSET 0x70
|
#define NANDF1ECC_OFFSET 0x70
|
||||||
|
@ -83,6 +80,9 @@ struct davinci_nand_pdata { /* platform_data */
|
||||||
/* Main and mirror bbt descriptor overrides */
|
/* Main and mirror bbt descriptor overrides */
|
||||||
struct nand_bbt_descr *bbt_td;
|
struct nand_bbt_descr *bbt_td;
|
||||||
struct nand_bbt_descr *bbt_md;
|
struct nand_bbt_descr *bbt_md;
|
||||||
|
|
||||||
|
/* Access timings */
|
||||||
|
struct davinci_aemif_timing *timing;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __ARCH_ARM_DAVINCI_NAND_H */
|
#endif /* __ARCH_ARM_DAVINCI_NAND_H */
|
||||||
|
|
|
@ -172,6 +172,7 @@
|
||||||
#define DA8XX_LPSC1_UART2 13
|
#define DA8XX_LPSC1_UART2 13
|
||||||
#define DA8XX_LPSC1_LCDC 16
|
#define DA8XX_LPSC1_LCDC 16
|
||||||
#define DA8XX_LPSC1_PWM 17
|
#define DA8XX_LPSC1_PWM 17
|
||||||
|
#define DA850_LPSC1_MMC_SD1 18
|
||||||
#define DA8XX_LPSC1_ECAP 20
|
#define DA8XX_LPSC1_ECAP 20
|
||||||
#define DA830_LPSC1_EQEP 21
|
#define DA830_LPSC1_EQEP 21
|
||||||
#define DA850_LPSC1_TPTC2 21
|
#define DA850_LPSC1_TPTC2 21
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <linux/serial_8250.h>
|
#include <linux/serial_8250.h>
|
||||||
|
#include <linux/input/matrix_keypad.h>
|
||||||
|
|
||||||
#include <mach/mmc.h>
|
#include <mach/mmc.h>
|
||||||
#include <mach/nand.h>
|
#include <mach/nand.h>
|
||||||
#include <mach/serial.h>
|
#include <mach/serial.h>
|
||||||
|
@ -41,6 +43,7 @@ struct tnetv107x_device_info {
|
||||||
struct davinci_uart_config *serial_config;
|
struct davinci_uart_config *serial_config;
|
||||||
struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */
|
struct davinci_mmc_config *mmc_config[2]; /* 2 controllers */
|
||||||
struct davinci_nand_pdata *nand_config[4]; /* 4 chipsels */
|
struct davinci_nand_pdata *nand_config[4]; /* 4 chipsels */
|
||||||
|
struct matrix_keypad_platform_data *keypad_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct platform_device tnetv107x_wdt_device;
|
extern struct platform_device tnetv107x_wdt_device;
|
||||||
|
|
|
@ -88,6 +88,8 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
|
||||||
/* DA8xx boards */
|
/* DA8xx boards */
|
||||||
DEBUG_LL_DA8XX(davinci_da830_evm, 2);
|
DEBUG_LL_DA8XX(davinci_da830_evm, 2);
|
||||||
DEBUG_LL_DA8XX(davinci_da850_evm, 2);
|
DEBUG_LL_DA8XX(davinci_da850_evm, 2);
|
||||||
|
DEBUG_LL_DA8XX(mityomapl138, 1);
|
||||||
|
DEBUG_LL_DA8XX(omapl138_hawkboard, 2);
|
||||||
|
|
||||||
/* TNETV107x boards */
|
/* TNETV107x boards */
|
||||||
DEBUG_LL_TNETV107X(tnetv107x, 1);
|
DEBUG_LL_TNETV107X(tnetv107x, 1);
|
||||||
|
|
|
@ -104,7 +104,7 @@ static u32 pll_ext_freq[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PSC control registers */
|
/* PSC control registers */
|
||||||
static u32 psc_regs[] __initconst = { TNETV107X_PSC_BASE };
|
static u32 psc_regs[] = { TNETV107X_PSC_BASE };
|
||||||
|
|
||||||
/* Host map for interrupt controller */
|
/* Host map for interrupt controller */
|
||||||
static u32 intc_host_map[] = { 0x01010000, 0x01010101, -1 };
|
static u32 intc_host_map[] = { 0x01010000, 0x01010101, -1 };
|
||||||
|
@ -581,7 +581,14 @@ static struct davinci_id ids[] = {
|
||||||
.part_no = 0xb8a1,
|
.part_no = 0xb8a1,
|
||||||
.manufacturer = 0x017,
|
.manufacturer = 0x017,
|
||||||
.cpu_id = DAVINCI_CPU_ID_TNETV107X,
|
.cpu_id = DAVINCI_CPU_ID_TNETV107X,
|
||||||
.name = "tnetv107x rev1.0",
|
.name = "tnetv107x rev 1.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.variant = 0x1,
|
||||||
|
.part_no = 0xb8a1,
|
||||||
|
.manufacturer = 0x017,
|
||||||
|
.cpu_id = DAVINCI_CPU_ID_TNETV107X,
|
||||||
|
.name = "tnetv107x rev 1.1/1.2",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/i2c/pca953x.h>
|
#include <linux/i2c/pca953x.h>
|
||||||
|
@ -38,19 +39,37 @@
|
||||||
|
|
||||||
#include "mux.h"
|
#include "mux.h"
|
||||||
|
|
||||||
#define AM35XX_EVM_PHY_MASK (0xF)
|
|
||||||
#define AM35XX_EVM_MDIO_FREQUENCY (1000000)
|
#define AM35XX_EVM_MDIO_FREQUENCY (1000000)
|
||||||
|
|
||||||
|
static struct mdio_platform_data am3517_evm_mdio_pdata = {
|
||||||
|
.bus_freq = AM35XX_EVM_MDIO_FREQUENCY,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct resource am3517_mdio_resources[] = {
|
||||||
|
{
|
||||||
|
.start = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET,
|
||||||
|
.end = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET +
|
||||||
|
SZ_4K - 1,
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device am3517_mdio_device = {
|
||||||
|
.name = "davinci_mdio",
|
||||||
|
.id = 0,
|
||||||
|
.num_resources = ARRAY_SIZE(am3517_mdio_resources),
|
||||||
|
.resource = am3517_mdio_resources,
|
||||||
|
.dev.platform_data = &am3517_evm_mdio_pdata,
|
||||||
|
};
|
||||||
|
|
||||||
static struct emac_platform_data am3517_evm_emac_pdata = {
|
static struct emac_platform_data am3517_evm_emac_pdata = {
|
||||||
.phy_mask = AM35XX_EVM_PHY_MASK,
|
|
||||||
.mdio_max_freq = AM35XX_EVM_MDIO_FREQUENCY,
|
|
||||||
.rmii_en = 1,
|
.rmii_en = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct resource am3517_emac_resources[] = {
|
static struct resource am3517_emac_resources[] = {
|
||||||
{
|
{
|
||||||
.start = AM35XX_IPSS_EMAC_BASE,
|
.start = AM35XX_IPSS_EMAC_BASE,
|
||||||
.end = AM35XX_IPSS_EMAC_BASE + 0x3FFFF,
|
.end = AM35XX_IPSS_EMAC_BASE + 0x2FFFF,
|
||||||
.flags = IORESOURCE_MEM,
|
.flags = IORESOURCE_MEM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -113,7 +132,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
|
||||||
pdata->ctrl_reg_offset = AM35XX_EMAC_CNTRL_OFFSET;
|
pdata->ctrl_reg_offset = AM35XX_EMAC_CNTRL_OFFSET;
|
||||||
pdata->ctrl_mod_reg_offset = AM35XX_EMAC_CNTRL_MOD_OFFSET;
|
pdata->ctrl_mod_reg_offset = AM35XX_EMAC_CNTRL_MOD_OFFSET;
|
||||||
pdata->ctrl_ram_offset = AM35XX_EMAC_CNTRL_RAM_OFFSET;
|
pdata->ctrl_ram_offset = AM35XX_EMAC_CNTRL_RAM_OFFSET;
|
||||||
pdata->mdio_reg_offset = AM35XX_EMAC_MDIO_OFFSET;
|
|
||||||
pdata->ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE;
|
pdata->ctrl_ram_size = AM35XX_EMAC_CNTRL_RAM_SIZE;
|
||||||
pdata->version = EMAC_VERSION_2;
|
pdata->version = EMAC_VERSION_2;
|
||||||
pdata->hw_ram_addr = AM35XX_EMAC_HW_RAM_ADDR;
|
pdata->hw_ram_addr = AM35XX_EMAC_HW_RAM_ADDR;
|
||||||
|
@ -121,6 +139,9 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
|
||||||
pdata->interrupt_disable = am3517_disable_ethernet_int;
|
pdata->interrupt_disable = am3517_disable_ethernet_int;
|
||||||
am3517_emac_device.dev.platform_data = pdata;
|
am3517_emac_device.dev.platform_data = pdata;
|
||||||
platform_device_register(&am3517_emac_device);
|
platform_device_register(&am3517_emac_device);
|
||||||
|
platform_device_register(&am3517_mdio_device);
|
||||||
|
clk_add_alias(NULL, dev_name(&am3517_mdio_device.dev),
|
||||||
|
NULL, &am3517_emac_device.dev);
|
||||||
|
|
||||||
regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
|
regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
|
||||||
regval = regval & (~(AM35XX_CPGMACSS_SW_RST));
|
regval = regval & (~(AM35XX_CPGMACSS_SW_RST));
|
||||||
|
|
|
@ -424,6 +424,15 @@ config KEYBOARD_OMAP
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called omap-keypad.
|
module will be called omap-keypad.
|
||||||
|
|
||||||
|
config KEYBOARD_TNETV107X
|
||||||
|
tristate "TI TNETV107X keypad support"
|
||||||
|
depends on ARCH_DAVINCI_TNETV107X
|
||||||
|
help
|
||||||
|
Say Y here if you want to use the TNETV107X keypad.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called tnetv107x-keypad.
|
||||||
|
|
||||||
config KEYBOARD_TWL4030
|
config KEYBOARD_TWL4030
|
||||||
tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
|
tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
|
||||||
depends on TWL4030_CORE
|
depends on TWL4030_CORE
|
||||||
|
|
|
@ -38,6 +38,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
|
||||||
obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
|
obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
|
||||||
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
|
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
|
||||||
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
|
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
|
||||||
|
obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o
|
||||||
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
|
obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o
|
||||||
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
|
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
|
||||||
obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
|
obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o
|
||||||
|
|
|
@ -0,0 +1,340 @@
|
||||||
|
/*
|
||||||
|
* Texas Instruments TNETV107X Keypad Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Texas Instruments
|
||||||
|
*
|
||||||
|
* 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 version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||||
|
* kind, whether express or implied; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/input/matrix_keypad.h>
|
||||||
|
|
||||||
|
#define BITS(x) (BIT(x) - 1)
|
||||||
|
|
||||||
|
#define KEYPAD_ROWS 9
|
||||||
|
#define KEYPAD_COLS 9
|
||||||
|
|
||||||
|
#define DEBOUNCE_MIN 0x400ul
|
||||||
|
#define DEBOUNCE_MAX 0x3ffffffful
|
||||||
|
|
||||||
|
struct keypad_regs {
|
||||||
|
u32 rev;
|
||||||
|
u32 mode;
|
||||||
|
u32 mask;
|
||||||
|
u32 pol;
|
||||||
|
u32 dclock;
|
||||||
|
u32 rclock;
|
||||||
|
u32 stable_cnt;
|
||||||
|
u32 in_en;
|
||||||
|
u32 out;
|
||||||
|
u32 out_en;
|
||||||
|
u32 in;
|
||||||
|
u32 lock;
|
||||||
|
u32 pres[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define keypad_read(kp, reg) __raw_readl(&(kp)->regs->reg)
|
||||||
|
#define keypad_write(kp, reg, val) __raw_writel(val, &(kp)->regs->reg)
|
||||||
|
|
||||||
|
struct keypad_data {
|
||||||
|
struct input_dev *input_dev;
|
||||||
|
struct resource *res;
|
||||||
|
struct keypad_regs __iomem *regs;
|
||||||
|
struct clk *clk;
|
||||||
|
struct device *dev;
|
||||||
|
spinlock_t lock;
|
||||||
|
u32 irq_press;
|
||||||
|
u32 irq_release;
|
||||||
|
int rows, cols, row_shift;
|
||||||
|
int debounce_ms, active_low;
|
||||||
|
u32 prev_keys[3];
|
||||||
|
unsigned short keycodes[];
|
||||||
|
};
|
||||||
|
|
||||||
|
static irqreturn_t keypad_irq(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct keypad_data *kp = data;
|
||||||
|
int i, bit, val, row, col, code;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 curr_keys[3];
|
||||||
|
u32 change;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&kp->lock, flags);
|
||||||
|
|
||||||
|
memset(curr_keys, 0, sizeof(curr_keys));
|
||||||
|
if (irq == kp->irq_press)
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
curr_keys[i] = keypad_read(kp, pres[i]);
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
change = curr_keys[i] ^ kp->prev_keys[i];
|
||||||
|
|
||||||
|
while (change) {
|
||||||
|
bit = fls(change) - 1;
|
||||||
|
change ^= BIT(bit);
|
||||||
|
val = curr_keys[i] & BIT(bit);
|
||||||
|
bit += i * 32;
|
||||||
|
row = bit / KEYPAD_COLS;
|
||||||
|
col = bit % KEYPAD_COLS;
|
||||||
|
|
||||||
|
code = MATRIX_SCAN_CODE(row, col, kp->row_shift);
|
||||||
|
input_event(kp->input_dev, EV_MSC, MSC_SCAN, code);
|
||||||
|
input_report_key(kp->input_dev, kp->keycodes[code],
|
||||||
|
val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input_sync(kp->input_dev);
|
||||||
|
memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys));
|
||||||
|
|
||||||
|
if (irq == kp->irq_press)
|
||||||
|
keypad_write(kp, lock, 0); /* Allow hardware updates */
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&kp->lock, flags);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int keypad_start(struct input_dev *dev)
|
||||||
|
{
|
||||||
|
struct keypad_data *kp = input_get_drvdata(dev);
|
||||||
|
unsigned long mask, debounce, clk_rate_khz;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
clk_enable(kp->clk);
|
||||||
|
clk_rate_khz = clk_get_rate(kp->clk) / 1000;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&kp->lock, flags);
|
||||||
|
|
||||||
|
/* Initialize device registers */
|
||||||
|
keypad_write(kp, mode, 0);
|
||||||
|
|
||||||
|
mask = BITS(kp->rows) << KEYPAD_COLS;
|
||||||
|
mask |= BITS(kp->cols);
|
||||||
|
keypad_write(kp, mask, ~mask);
|
||||||
|
|
||||||
|
keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff);
|
||||||
|
keypad_write(kp, stable_cnt, 3);
|
||||||
|
|
||||||
|
debounce = kp->debounce_ms * clk_rate_khz;
|
||||||
|
debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX);
|
||||||
|
keypad_write(kp, dclock, debounce);
|
||||||
|
keypad_write(kp, rclock, 4 * debounce);
|
||||||
|
|
||||||
|
keypad_write(kp, in_en, 1);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&kp->lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keypad_stop(struct input_dev *dev)
|
||||||
|
{
|
||||||
|
struct keypad_data *kp = input_get_drvdata(dev);
|
||||||
|
|
||||||
|
synchronize_irq(kp->irq_press);
|
||||||
|
synchronize_irq(kp->irq_release);
|
||||||
|
clk_disable(kp->clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devinit keypad_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
const struct matrix_keypad_platform_data *pdata;
|
||||||
|
const struct matrix_keymap_data *keymap_data;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct keypad_data *kp;
|
||||||
|
int error = 0, sz, row_shift;
|
||||||
|
u32 rev = 0;
|
||||||
|
|
||||||
|
pdata = pdev->dev.platform_data;
|
||||||
|
if (!pdata) {
|
||||||
|
dev_err(dev, "cannot find device data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
keymap_data = pdata->keymap_data;
|
||||||
|
if (!keymap_data) {
|
||||||
|
dev_err(dev, "cannot find keymap data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
row_shift = get_count_order(pdata->num_col_gpios);
|
||||||
|
sz = offsetof(struct keypad_data, keycodes);
|
||||||
|
sz += (pdata->num_row_gpios << row_shift) * sizeof(kp->keycodes[0]);
|
||||||
|
kp = kzalloc(sz, GFP_KERNEL);
|
||||||
|
if (!kp) {
|
||||||
|
dev_err(dev, "cannot allocate device info\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
kp->dev = dev;
|
||||||
|
kp->rows = pdata->num_row_gpios;
|
||||||
|
kp->cols = pdata->num_col_gpios;
|
||||||
|
kp->row_shift = row_shift;
|
||||||
|
platform_set_drvdata(pdev, kp);
|
||||||
|
spin_lock_init(&kp->lock);
|
||||||
|
|
||||||
|
kp->irq_press = platform_get_irq_byname(pdev, "press");
|
||||||
|
kp->irq_release = platform_get_irq_byname(pdev, "release");
|
||||||
|
if (kp->irq_press < 0 || kp->irq_release < 0) {
|
||||||
|
dev_err(dev, "cannot determine device interrupts\n");
|
||||||
|
error = -ENODEV;
|
||||||
|
goto error_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!kp->res) {
|
||||||
|
dev_err(dev, "cannot determine register area\n");
|
||||||
|
error = -ENODEV;
|
||||||
|
goto error_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request_mem_region(kp->res->start, resource_size(kp->res),
|
||||||
|
pdev->name)) {
|
||||||
|
dev_err(dev, "cannot claim register memory\n");
|
||||||
|
kp->res = NULL;
|
||||||
|
error = -EINVAL;
|
||||||
|
goto error_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
kp->regs = ioremap(kp->res->start, resource_size(kp->res));
|
||||||
|
if (!kp->regs) {
|
||||||
|
dev_err(dev, "cannot map register memory\n");
|
||||||
|
error = -ENOMEM;
|
||||||
|
goto error_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
kp->clk = clk_get(dev, NULL);
|
||||||
|
if (!kp->clk) {
|
||||||
|
dev_err(dev, "cannot claim device clock\n");
|
||||||
|
error = -EINVAL;
|
||||||
|
goto error_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = request_threaded_irq(kp->irq_press, NULL, keypad_irq, 0,
|
||||||
|
dev_name(dev), kp);
|
||||||
|
if (error < 0) {
|
||||||
|
dev_err(kp->dev, "Could not allocate keypad press key irq\n");
|
||||||
|
goto error_irq_press;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = request_threaded_irq(kp->irq_release, NULL, keypad_irq, 0,
|
||||||
|
dev_name(dev), kp);
|
||||||
|
if (error < 0) {
|
||||||
|
dev_err(kp->dev, "Could not allocate keypad release key irq\n");
|
||||||
|
goto error_irq_release;
|
||||||
|
}
|
||||||
|
|
||||||
|
kp->input_dev = input_allocate_device();
|
||||||
|
if (!kp->input_dev) {
|
||||||
|
dev_err(dev, "cannot allocate input device\n");
|
||||||
|
error = -ENOMEM;
|
||||||
|
goto error_input;
|
||||||
|
}
|
||||||
|
input_set_drvdata(kp->input_dev, kp);
|
||||||
|
|
||||||
|
kp->input_dev->name = pdev->name;
|
||||||
|
kp->input_dev->dev.parent = &pdev->dev;
|
||||||
|
kp->input_dev->open = keypad_start;
|
||||||
|
kp->input_dev->close = keypad_stop;
|
||||||
|
kp->input_dev->evbit[0] = BIT_MASK(EV_KEY);
|
||||||
|
if (!pdata->no_autorepeat)
|
||||||
|
kp->input_dev->evbit[0] |= BIT_MASK(EV_REP);
|
||||||
|
|
||||||
|
clk_enable(kp->clk);
|
||||||
|
rev = keypad_read(kp, rev);
|
||||||
|
kp->input_dev->id.bustype = BUS_HOST;
|
||||||
|
kp->input_dev->id.product = ((rev >> 8) & 0x07);
|
||||||
|
kp->input_dev->id.version = ((rev >> 16) & 0xfff);
|
||||||
|
clk_disable(kp->clk);
|
||||||
|
|
||||||
|
kp->input_dev->keycode = kp->keycodes;
|
||||||
|
kp->input_dev->keycodesize = sizeof(kp->keycodes[0]);
|
||||||
|
kp->input_dev->keycodemax = kp->rows << kp->row_shift;
|
||||||
|
|
||||||
|
matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes,
|
||||||
|
kp->input_dev->keybit);
|
||||||
|
|
||||||
|
input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN);
|
||||||
|
|
||||||
|
error = input_register_device(kp->input_dev);
|
||||||
|
if (error < 0) {
|
||||||
|
dev_err(dev, "Could not register input device\n");
|
||||||
|
goto error_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
error_reg:
|
||||||
|
input_free_device(kp->input_dev);
|
||||||
|
error_input:
|
||||||
|
free_irq(kp->irq_release, kp);
|
||||||
|
error_irq_release:
|
||||||
|
free_irq(kp->irq_press, kp);
|
||||||
|
error_irq_press:
|
||||||
|
clk_put(kp->clk);
|
||||||
|
error_clk:
|
||||||
|
iounmap(kp->regs);
|
||||||
|
error_map:
|
||||||
|
release_mem_region(kp->res->start, resource_size(kp->res));
|
||||||
|
error_res:
|
||||||
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
kfree(kp);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit keypad_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct keypad_data *kp = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
free_irq(kp->irq_press, kp);
|
||||||
|
free_irq(kp->irq_release, kp);
|
||||||
|
input_unregister_device(kp->input_dev);
|
||||||
|
clk_put(kp->clk);
|
||||||
|
iounmap(kp->regs);
|
||||||
|
release_mem_region(kp->res->start, resource_size(kp->res));
|
||||||
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
kfree(kp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver keypad_driver = {
|
||||||
|
.probe = keypad_probe,
|
||||||
|
.remove = __devexit_p(keypad_remove),
|
||||||
|
.driver.name = "tnetv107x-keypad",
|
||||||
|
.driver.owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init keypad_init(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&keypad_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit keypad_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&keypad_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(keypad_init);
|
||||||
|
module_exit(keypad_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Cyril Chemparathy");
|
||||||
|
MODULE_DESCRIPTION("TNETV107X Keypad Driver");
|
||||||
|
MODULE_ALIAS("platform: tnetv107x-keypad");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -328,6 +328,15 @@ config TOUCHSCREEN_MIGOR
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called migor_ts.
|
module will be called migor_ts.
|
||||||
|
|
||||||
|
config TOUCHSCREEN_TNETV107X
|
||||||
|
tristate "TI TNETV107X touchscreen support"
|
||||||
|
depends on ARCH_DAVINCI_TNETV107X
|
||||||
|
help
|
||||||
|
Say Y here if you want to use the TNETV107X touchscreen.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called tnetv107x-ts.
|
||||||
|
|
||||||
config TOUCHSCREEN_TOUCHRIGHT
|
config TOUCHSCREEN_TOUCHRIGHT
|
||||||
tristate "Touchright serial touchscreen"
|
tristate "Touchright serial touchscreen"
|
||||||
select SERIO
|
select SERIO
|
||||||
|
|
|
@ -37,6 +37,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
|
||||||
obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o
|
obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o
|
||||||
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
|
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
|
||||||
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
|
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
|
||||||
|
obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
|
||||||
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
|
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
|
||||||
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
|
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
|
||||||
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
|
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
|
||||||
|
|
|
@ -0,0 +1,396 @@
|
||||||
|
/*
|
||||||
|
* Texas Instruments TNETV107X Touchscreen Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Texas Instruments
|
||||||
|
*
|
||||||
|
* 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 version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||||
|
* kind, whether express or implied; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
|
||||||
|
#include <mach/tnetv107x.h>
|
||||||
|
|
||||||
|
#define TSC_PENUP_POLL (HZ / 5)
|
||||||
|
#define IDLE_TIMEOUT 100 /* msec */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The first and last samples of a touch interval are usually garbage and need
|
||||||
|
* to be filtered out with these devices. The following definitions control
|
||||||
|
* the number of samples skipped.
|
||||||
|
*/
|
||||||
|
#define TSC_HEAD_SKIP 1
|
||||||
|
#define TSC_TAIL_SKIP 1
|
||||||
|
#define TSC_SKIP (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1)
|
||||||
|
#define TSC_SAMPLES (TSC_SKIP + 1)
|
||||||
|
|
||||||
|
/* Register Offsets */
|
||||||
|
struct tsc_regs {
|
||||||
|
u32 rev;
|
||||||
|
u32 tscm;
|
||||||
|
u32 bwcm;
|
||||||
|
u32 swc;
|
||||||
|
u32 adcchnl;
|
||||||
|
u32 adcdata;
|
||||||
|
u32 chval[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TSC Mode Configuration Register (tscm) bits */
|
||||||
|
#define WMODE BIT(0)
|
||||||
|
#define TSKIND BIT(1)
|
||||||
|
#define ZMEASURE_EN BIT(2)
|
||||||
|
#define IDLE BIT(3)
|
||||||
|
#define TSC_EN BIT(4)
|
||||||
|
#define STOP BIT(5)
|
||||||
|
#define ONE_SHOT BIT(6)
|
||||||
|
#define SINGLE BIT(7)
|
||||||
|
#define AVG BIT(8)
|
||||||
|
#define AVGNUM(x) (((x) & 0x03) << 9)
|
||||||
|
#define PVSTC(x) (((x) & 0x07) << 11)
|
||||||
|
#define PON BIT(14)
|
||||||
|
#define PONBG BIT(15)
|
||||||
|
#define AFERST BIT(16)
|
||||||
|
|
||||||
|
/* ADC DATA Capture Register bits */
|
||||||
|
#define DATA_VALID BIT(16)
|
||||||
|
|
||||||
|
/* Register Access Macros */
|
||||||
|
#define tsc_read(ts, reg) __raw_readl(&(ts)->regs->reg)
|
||||||
|
#define tsc_write(ts, reg, val) __raw_writel(val, &(ts)->regs->reg);
|
||||||
|
#define tsc_set_bits(ts, reg, val) \
|
||||||
|
tsc_write(ts, reg, tsc_read(ts, reg) | (val))
|
||||||
|
#define tsc_clr_bits(ts, reg, val) \
|
||||||
|
tsc_write(ts, reg, tsc_read(ts, reg) & ~(val))
|
||||||
|
|
||||||
|
struct sample {
|
||||||
|
int x, y, p;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tsc_data {
|
||||||
|
struct input_dev *input_dev;
|
||||||
|
struct resource *res;
|
||||||
|
struct tsc_regs __iomem *regs;
|
||||||
|
struct timer_list timer;
|
||||||
|
spinlock_t lock;
|
||||||
|
struct clk *clk;
|
||||||
|
struct device *dev;
|
||||||
|
int sample_count;
|
||||||
|
struct sample samples[TSC_SAMPLES];
|
||||||
|
int tsc_irq;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tsc_read_sample(struct tsc_data *ts, struct sample* sample)
|
||||||
|
{
|
||||||
|
int x, y, z1, z2, t, p = 0;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = tsc_read(ts, chval[0]);
|
||||||
|
if (val & DATA_VALID)
|
||||||
|
x = val & 0xffff;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
y = tsc_read(ts, chval[1]) & 0xffff;
|
||||||
|
z1 = tsc_read(ts, chval[2]) & 0xffff;
|
||||||
|
z2 = tsc_read(ts, chval[3]) & 0xffff;
|
||||||
|
|
||||||
|
if (z1) {
|
||||||
|
t = ((600 * x) * (z2 - z1));
|
||||||
|
p = t / (u32) (z1 << 12);
|
||||||
|
if (p < 0)
|
||||||
|
p = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sample->x = x;
|
||||||
|
sample->y = y;
|
||||||
|
sample->p = p;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tsc_poll(unsigned long data)
|
||||||
|
{
|
||||||
|
struct tsc_data *ts = (struct tsc_data *)data;
|
||||||
|
unsigned long flags;
|
||||||
|
int i, val, x, y, p;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ts->lock, flags);
|
||||||
|
|
||||||
|
if (ts->sample_count >= TSC_SKIP) {
|
||||||
|
input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
|
||||||
|
input_report_key(ts->input_dev, BTN_TOUCH, 0);
|
||||||
|
input_sync(ts->input_dev);
|
||||||
|
} else if (ts->sample_count > 0) {
|
||||||
|
/*
|
||||||
|
* A touch event lasted less than our skip count. Salvage and
|
||||||
|
* report anyway.
|
||||||
|
*/
|
||||||
|
for (i = 0, val = 0; i < ts->sample_count; i++)
|
||||||
|
val += ts->samples[i].x;
|
||||||
|
x = val / ts->sample_count;
|
||||||
|
|
||||||
|
for (i = 0, val = 0; i < ts->sample_count; i++)
|
||||||
|
val += ts->samples[i].y;
|
||||||
|
y = val / ts->sample_count;
|
||||||
|
|
||||||
|
for (i = 0, val = 0; i < ts->sample_count; i++)
|
||||||
|
val += ts->samples[i].p;
|
||||||
|
p = val / ts->sample_count;
|
||||||
|
|
||||||
|
input_report_abs(ts->input_dev, ABS_X, x);
|
||||||
|
input_report_abs(ts->input_dev, ABS_Y, y);
|
||||||
|
input_report_abs(ts->input_dev, ABS_PRESSURE, p);
|
||||||
|
input_report_key(ts->input_dev, BTN_TOUCH, 1);
|
||||||
|
input_sync(ts->input_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
ts->sample_count = 0;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&ts->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t tsc_irq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct tsc_data *ts = (struct tsc_data *)dev_id;
|
||||||
|
struct sample *sample;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
spin_lock(&ts->lock);
|
||||||
|
|
||||||
|
index = ts->sample_count % TSC_SAMPLES;
|
||||||
|
sample = &ts->samples[index];
|
||||||
|
if (tsc_read_sample(ts, sample) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (++ts->sample_count >= TSC_SKIP) {
|
||||||
|
index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES;
|
||||||
|
sample = &ts->samples[index];
|
||||||
|
|
||||||
|
input_report_abs(ts->input_dev, ABS_X, sample->x);
|
||||||
|
input_report_abs(ts->input_dev, ABS_Y, sample->y);
|
||||||
|
input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p);
|
||||||
|
if (ts->sample_count == TSC_SKIP)
|
||||||
|
input_report_key(ts->input_dev, BTN_TOUCH, 1);
|
||||||
|
input_sync(ts->input_dev);
|
||||||
|
}
|
||||||
|
mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL);
|
||||||
|
out:
|
||||||
|
spin_unlock(&ts->lock);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tsc_start(struct input_dev *dev)
|
||||||
|
{
|
||||||
|
struct tsc_data *ts = input_get_drvdata(dev);
|
||||||
|
unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT);
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
clk_enable(ts->clk);
|
||||||
|
|
||||||
|
/* Go to idle mode, before any initialization */
|
||||||
|
while (time_after(timeout, jiffies)) {
|
||||||
|
if (tsc_read(ts, tscm) & IDLE)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time_before(timeout, jiffies)) {
|
||||||
|
dev_warn(ts->dev, "timeout waiting for idle\n");
|
||||||
|
clk_disable(ts->clk);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure TSC Control register*/
|
||||||
|
val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN);
|
||||||
|
tsc_write(ts, tscm, val);
|
||||||
|
|
||||||
|
/* Bring TSC out of reset: Clear AFE reset bit */
|
||||||
|
val &= ~(AFERST);
|
||||||
|
tsc_write(ts, tscm, val);
|
||||||
|
|
||||||
|
/* Configure all pins for hardware control*/
|
||||||
|
tsc_write(ts, bwcm, 0);
|
||||||
|
|
||||||
|
/* Finally enable the TSC */
|
||||||
|
tsc_set_bits(ts, tscm, TSC_EN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tsc_stop(struct input_dev *dev)
|
||||||
|
{
|
||||||
|
struct tsc_data *ts = input_get_drvdata(dev);
|
||||||
|
|
||||||
|
tsc_clr_bits(ts, tscm, TSC_EN);
|
||||||
|
synchronize_irq(ts->tsc_irq);
|
||||||
|
del_timer_sync(&ts->timer);
|
||||||
|
clk_disable(ts->clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devinit tsc_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct tsc_data *ts;
|
||||||
|
int error = 0;
|
||||||
|
u32 rev = 0;
|
||||||
|
|
||||||
|
ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL);
|
||||||
|
if (!ts) {
|
||||||
|
dev_err(dev, "cannot allocate device info\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ts->dev = dev;
|
||||||
|
spin_lock_init(&ts->lock);
|
||||||
|
setup_timer(&ts->timer, tsc_poll, (unsigned long)ts);
|
||||||
|
platform_set_drvdata(pdev, ts);
|
||||||
|
|
||||||
|
ts->tsc_irq = platform_get_irq(pdev, 0);
|
||||||
|
if (ts->tsc_irq < 0) {
|
||||||
|
dev_err(dev, "cannot determine device interrupt\n");
|
||||||
|
error = -ENODEV;
|
||||||
|
goto error_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!ts->res) {
|
||||||
|
dev_err(dev, "cannot determine register area\n");
|
||||||
|
error = -ENODEV;
|
||||||
|
goto error_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!request_mem_region(ts->res->start, resource_size(ts->res),
|
||||||
|
pdev->name)) {
|
||||||
|
dev_err(dev, "cannot claim register memory\n");
|
||||||
|
ts->res = NULL;
|
||||||
|
error = -EINVAL;
|
||||||
|
goto error_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ts->regs = ioremap(ts->res->start, resource_size(ts->res));
|
||||||
|
if (!ts->regs) {
|
||||||
|
dev_err(dev, "cannot map register memory\n");
|
||||||
|
error = -ENOMEM;
|
||||||
|
goto error_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
ts->clk = clk_get(dev, NULL);
|
||||||
|
if (!ts->clk) {
|
||||||
|
dev_err(dev, "cannot claim device clock\n");
|
||||||
|
error = -EINVAL;
|
||||||
|
goto error_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, 0,
|
||||||
|
dev_name(dev), ts);
|
||||||
|
if (error < 0) {
|
||||||
|
dev_err(ts->dev, "Could not allocate ts irq\n");
|
||||||
|
goto error_irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
ts->input_dev = input_allocate_device();
|
||||||
|
if (!ts->input_dev) {
|
||||||
|
dev_err(dev, "cannot allocate input device\n");
|
||||||
|
error = -ENOMEM;
|
||||||
|
goto error_input;
|
||||||
|
}
|
||||||
|
input_set_drvdata(ts->input_dev, ts);
|
||||||
|
|
||||||
|
ts->input_dev->name = pdev->name;
|
||||||
|
ts->input_dev->id.bustype = BUS_HOST;
|
||||||
|
ts->input_dev->dev.parent = &pdev->dev;
|
||||||
|
ts->input_dev->open = tsc_start;
|
||||||
|
ts->input_dev->close = tsc_stop;
|
||||||
|
|
||||||
|
clk_enable(ts->clk);
|
||||||
|
rev = tsc_read(ts, rev);
|
||||||
|
ts->input_dev->id.product = ((rev >> 8) & 0x07);
|
||||||
|
ts->input_dev->id.version = ((rev >> 16) & 0xfff);
|
||||||
|
clk_disable(ts->clk);
|
||||||
|
|
||||||
|
__set_bit(EV_KEY, ts->input_dev->evbit);
|
||||||
|
__set_bit(EV_ABS, ts->input_dev->evbit);
|
||||||
|
__set_bit(BTN_TOUCH, ts->input_dev->keybit);
|
||||||
|
|
||||||
|
input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0);
|
||||||
|
input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0);
|
||||||
|
input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0);
|
||||||
|
|
||||||
|
error = input_register_device(ts->input_dev);
|
||||||
|
if (error < 0) {
|
||||||
|
dev_err(dev, "failed input device registration\n");
|
||||||
|
goto error_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error_reg:
|
||||||
|
input_free_device(ts->input_dev);
|
||||||
|
error_input:
|
||||||
|
free_irq(ts->tsc_irq, ts);
|
||||||
|
error_irq:
|
||||||
|
clk_put(ts->clk);
|
||||||
|
error_clk:
|
||||||
|
iounmap(ts->regs);
|
||||||
|
error_map:
|
||||||
|
release_mem_region(ts->res->start, resource_size(ts->res));
|
||||||
|
error_res:
|
||||||
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
kfree(ts);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit tsc_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct tsc_data *ts = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
input_unregister_device(ts->input_dev);
|
||||||
|
free_irq(ts->tsc_irq, ts);
|
||||||
|
clk_put(ts->clk);
|
||||||
|
iounmap(ts->regs);
|
||||||
|
release_mem_region(ts->res->start, resource_size(ts->res));
|
||||||
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
kfree(ts);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver tsc_driver = {
|
||||||
|
.probe = tsc_probe,
|
||||||
|
.remove = __devexit_p(tsc_remove),
|
||||||
|
.driver.name = "tnetv107x-ts",
|
||||||
|
.driver.owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init tsc_init(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&tsc_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit tsc_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&tsc_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(tsc_init);
|
||||||
|
module_exit(tsc_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Cyril Chemparathy");
|
||||||
|
MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
|
||||||
|
MODULE_ALIAS("platform: tnetv107x-ts");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -35,6 +35,7 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include <mach/nand.h>
|
#include <mach/nand.h>
|
||||||
|
#include <mach/aemif.h>
|
||||||
|
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
|
|
||||||
|
@ -74,6 +75,8 @@ struct davinci_nand_info {
|
||||||
uint32_t mask_cle;
|
uint32_t mask_cle;
|
||||||
|
|
||||||
uint32_t core_chipsel;
|
uint32_t core_chipsel;
|
||||||
|
|
||||||
|
struct davinci_aemif_timing *timing;
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(davinci_nand_lock);
|
static DEFINE_SPINLOCK(davinci_nand_lock);
|
||||||
|
@ -478,36 +481,6 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
|
||||||
return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
|
return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
|
|
||||||
{
|
|
||||||
uint32_t regval, a1cr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NAND FLASH timings @ PLL1 == 459 MHz
|
|
||||||
* - AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz
|
|
||||||
* - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns
|
|
||||||
*/
|
|
||||||
regval = 0
|
|
||||||
| (0 << 31) /* selectStrobe */
|
|
||||||
| (0 << 30) /* extWait (never with NAND) */
|
|
||||||
| (1 << 26) /* writeSetup 10 ns */
|
|
||||||
| (3 << 20) /* writeStrobe 40 ns */
|
|
||||||
| (1 << 17) /* writeHold 10 ns */
|
|
||||||
| (0 << 13) /* readSetup 10 ns */
|
|
||||||
| (3 << 7) /* readStrobe 60 ns */
|
|
||||||
| (0 << 4) /* readHold 10 ns */
|
|
||||||
| (3 << 2) /* turnAround ?? ns */
|
|
||||||
| (0 << 0) /* asyncSize 8-bit bus */
|
|
||||||
;
|
|
||||||
a1cr = davinci_nand_readl(info, A1CR_OFFSET);
|
|
||||||
if (a1cr != regval) {
|
|
||||||
dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \
|
|
||||||
"reg to 0x%08x, was 0x%08x, should be done by " \
|
|
||||||
"bootloader.\n", regval, a1cr);
|
|
||||||
davinci_nand_writel(info, A1CR_OFFSET, regval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* An ECC layout for using 4-bit ECC with small-page flash, storing
|
/* An ECC layout for using 4-bit ECC with small-page flash, storing
|
||||||
|
@ -611,6 +584,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
|
||||||
info->chip.options = pdata->options;
|
info->chip.options = pdata->options;
|
||||||
info->chip.bbt_td = pdata->bbt_td;
|
info->chip.bbt_td = pdata->bbt_td;
|
||||||
info->chip.bbt_md = pdata->bbt_md;
|
info->chip.bbt_md = pdata->bbt_md;
|
||||||
|
info->timing = pdata->timing;
|
||||||
|
|
||||||
info->ioaddr = (uint32_t __force) vaddr;
|
info->ioaddr = (uint32_t __force) vaddr;
|
||||||
|
|
||||||
|
@ -688,15 +662,25 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
|
||||||
goto err_clk_enable;
|
goto err_clk_enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EMIF timings should normally be set by the boot loader,
|
/*
|
||||||
* especially after boot-from-NAND. The *only* reason to
|
* Setup Async configuration register in case we did not boot from
|
||||||
* have this special casing for the DM6446 EVM is to work
|
* NAND and so bootloader did not bother to set it up.
|
||||||
* with boot-from-NOR ... with CS0 manually re-jumpered
|
|
||||||
* (after startup) so it addresses the NAND flash, not NOR.
|
|
||||||
* Even for dev boards, that's unusually rude...
|
|
||||||
*/
|
*/
|
||||||
if (machine_is_davinci_evm())
|
val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
|
||||||
nand_dm6446evm_flash_init(info);
|
|
||||||
|
/* Extended Wait is not valid and Select Strobe mode is not used */
|
||||||
|
val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
|
||||||
|
if (info->chip.options & NAND_BUSWIDTH_16)
|
||||||
|
val |= 0x1;
|
||||||
|
|
||||||
|
davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
|
||||||
|
|
||||||
|
ret = davinci_aemif_setup_timing(info->timing, info->base,
|
||||||
|
info->core_chipsel);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
|
||||||
|
goto err_timing;
|
||||||
|
}
|
||||||
|
|
||||||
spin_lock_irq(&davinci_nand_lock);
|
spin_lock_irq(&davinci_nand_lock);
|
||||||
|
|
||||||
|
@ -809,6 +793,7 @@ syndrome_done:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_scan:
|
err_scan:
|
||||||
|
err_timing:
|
||||||
clk_disable(info->clk);
|
clk_disable(info->clk);
|
||||||
|
|
||||||
err_clk_enable:
|
err_clk_enable:
|
||||||
|
|
|
@ -954,6 +954,8 @@ config NET_NETX
|
||||||
config TI_DAVINCI_EMAC
|
config TI_DAVINCI_EMAC
|
||||||
tristate "TI DaVinci EMAC Support"
|
tristate "TI DaVinci EMAC Support"
|
||||||
depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
|
depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
|
||||||
|
select TI_DAVINCI_MDIO
|
||||||
|
select TI_DAVINCI_CPDMA
|
||||||
select PHYLIB
|
select PHYLIB
|
||||||
help
|
help
|
||||||
This driver supports TI's DaVinci Ethernet .
|
This driver supports TI's DaVinci Ethernet .
|
||||||
|
@ -961,6 +963,25 @@ config TI_DAVINCI_EMAC
|
||||||
To compile this driver as a module, choose M here: the module
|
To compile this driver as a module, choose M here: the module
|
||||||
will be called davinci_emac_driver. This is recommended.
|
will be called davinci_emac_driver. This is recommended.
|
||||||
|
|
||||||
|
config TI_DAVINCI_MDIO
|
||||||
|
tristate "TI DaVinci MDIO Support"
|
||||||
|
depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
|
||||||
|
select PHYLIB
|
||||||
|
help
|
||||||
|
This driver supports TI's DaVinci MDIO module.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the module
|
||||||
|
will be called davinci_mdio. This is recommended.
|
||||||
|
|
||||||
|
config TI_DAVINCI_CPDMA
|
||||||
|
tristate "TI DaVinci CPDMA Support"
|
||||||
|
depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
|
||||||
|
help
|
||||||
|
This driver supports TI's DaVinci CPDMA dma engine.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the module
|
||||||
|
will be called davinci_cpdma. This is recommended.
|
||||||
|
|
||||||
config DM9000
|
config DM9000
|
||||||
tristate "DM9000 support"
|
tristate "DM9000 support"
|
||||||
depends on ARM || BLACKFIN || MIPS
|
depends on ARM || BLACKFIN || MIPS
|
||||||
|
|
|
@ -7,6 +7,8 @@ obj-$(CONFIG_MDIO) += mdio.o
|
||||||
obj-$(CONFIG_PHYLIB) += phy/
|
obj-$(CONFIG_PHYLIB) += phy/
|
||||||
|
|
||||||
obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
|
obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
|
||||||
|
obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
|
||||||
|
obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
|
||||||
|
|
||||||
obj-$(CONFIG_E1000) += e1000/
|
obj-$(CONFIG_E1000) += e1000/
|
||||||
obj-$(CONFIG_E1000E) += e1000e/
|
obj-$(CONFIG_E1000E) += e1000e/
|
||||||
|
|
|
@ -0,0 +1,965 @@
|
||||||
|
/*
|
||||||
|
* Texas Instruments CPDMA Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Texas Instruments
|
||||||
|
*
|
||||||
|
* 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 version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||||
|
* kind, whether express or implied; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
#include "davinci_cpdma.h"
|
||||||
|
|
||||||
|
/* DMA Registers */
|
||||||
|
#define CPDMA_TXIDVER 0x00
|
||||||
|
#define CPDMA_TXCONTROL 0x04
|
||||||
|
#define CPDMA_TXTEARDOWN 0x08
|
||||||
|
#define CPDMA_RXIDVER 0x10
|
||||||
|
#define CPDMA_RXCONTROL 0x14
|
||||||
|
#define CPDMA_SOFTRESET 0x1c
|
||||||
|
#define CPDMA_RXTEARDOWN 0x18
|
||||||
|
#define CPDMA_TXINTSTATRAW 0x80
|
||||||
|
#define CPDMA_TXINTSTATMASKED 0x84
|
||||||
|
#define CPDMA_TXINTMASKSET 0x88
|
||||||
|
#define CPDMA_TXINTMASKCLEAR 0x8c
|
||||||
|
#define CPDMA_MACINVECTOR 0x90
|
||||||
|
#define CPDMA_MACEOIVECTOR 0x94
|
||||||
|
#define CPDMA_RXINTSTATRAW 0xa0
|
||||||
|
#define CPDMA_RXINTSTATMASKED 0xa4
|
||||||
|
#define CPDMA_RXINTMASKSET 0xa8
|
||||||
|
#define CPDMA_RXINTMASKCLEAR 0xac
|
||||||
|
#define CPDMA_DMAINTSTATRAW 0xb0
|
||||||
|
#define CPDMA_DMAINTSTATMASKED 0xb4
|
||||||
|
#define CPDMA_DMAINTMASKSET 0xb8
|
||||||
|
#define CPDMA_DMAINTMASKCLEAR 0xbc
|
||||||
|
#define CPDMA_DMAINT_HOSTERR BIT(1)
|
||||||
|
|
||||||
|
/* the following exist only if has_ext_regs is set */
|
||||||
|
#define CPDMA_DMACONTROL 0x20
|
||||||
|
#define CPDMA_DMASTATUS 0x24
|
||||||
|
#define CPDMA_RXBUFFOFS 0x28
|
||||||
|
#define CPDMA_EM_CONTROL 0x2c
|
||||||
|
|
||||||
|
/* Descriptor mode bits */
|
||||||
|
#define CPDMA_DESC_SOP BIT(31)
|
||||||
|
#define CPDMA_DESC_EOP BIT(30)
|
||||||
|
#define CPDMA_DESC_OWNER BIT(29)
|
||||||
|
#define CPDMA_DESC_EOQ BIT(28)
|
||||||
|
#define CPDMA_DESC_TD_COMPLETE BIT(27)
|
||||||
|
#define CPDMA_DESC_PASS_CRC BIT(26)
|
||||||
|
|
||||||
|
#define CPDMA_TEARDOWN_VALUE 0xfffffffc
|
||||||
|
|
||||||
|
struct cpdma_desc {
|
||||||
|
/* hardware fields */
|
||||||
|
u32 hw_next;
|
||||||
|
u32 hw_buffer;
|
||||||
|
u32 hw_len;
|
||||||
|
u32 hw_mode;
|
||||||
|
/* software fields */
|
||||||
|
void *sw_token;
|
||||||
|
u32 sw_buffer;
|
||||||
|
u32 sw_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpdma_desc_pool {
|
||||||
|
u32 phys;
|
||||||
|
void __iomem *iomap; /* ioremap map */
|
||||||
|
void *cpumap; /* dma_alloc map */
|
||||||
|
int desc_size, mem_size;
|
||||||
|
int num_desc, used_desc;
|
||||||
|
unsigned long *bitmap;
|
||||||
|
struct device *dev;
|
||||||
|
spinlock_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum cpdma_state {
|
||||||
|
CPDMA_STATE_IDLE,
|
||||||
|
CPDMA_STATE_ACTIVE,
|
||||||
|
CPDMA_STATE_TEARDOWN,
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *cpdma_state_str[] = { "idle", "active", "teardown" };
|
||||||
|
|
||||||
|
struct cpdma_ctlr {
|
||||||
|
enum cpdma_state state;
|
||||||
|
struct cpdma_params params;
|
||||||
|
struct device *dev;
|
||||||
|
struct cpdma_desc_pool *pool;
|
||||||
|
spinlock_t lock;
|
||||||
|
struct cpdma_chan *channels[2 * CPDMA_MAX_CHANNELS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpdma_chan {
|
||||||
|
enum cpdma_state state;
|
||||||
|
struct cpdma_ctlr *ctlr;
|
||||||
|
int chan_num;
|
||||||
|
spinlock_t lock;
|
||||||
|
struct cpdma_desc __iomem *head, *tail;
|
||||||
|
int count;
|
||||||
|
void __iomem *hdp, *cp, *rxfree;
|
||||||
|
u32 mask;
|
||||||
|
cpdma_handler_fn handler;
|
||||||
|
enum dma_data_direction dir;
|
||||||
|
struct cpdma_chan_stats stats;
|
||||||
|
/* offsets into dmaregs */
|
||||||
|
int int_set, int_clear, td;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The following make access to common cpdma_ctlr params more readable */
|
||||||
|
#define dmaregs params.dmaregs
|
||||||
|
#define num_chan params.num_chan
|
||||||
|
|
||||||
|
/* various accessors */
|
||||||
|
#define dma_reg_read(ctlr, ofs) __raw_readl((ctlr)->dmaregs + (ofs))
|
||||||
|
#define chan_read(chan, fld) __raw_readl((chan)->fld)
|
||||||
|
#define desc_read(desc, fld) __raw_readl(&(desc)->fld)
|
||||||
|
#define dma_reg_write(ctlr, ofs, v) __raw_writel(v, (ctlr)->dmaregs + (ofs))
|
||||||
|
#define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld)
|
||||||
|
#define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci
|
||||||
|
* emac) have dedicated on-chip memory for these descriptors. Some other
|
||||||
|
* devices (e.g. cpsw switches) use plain old memory. Descriptor pools
|
||||||
|
* abstract out these details
|
||||||
|
*/
|
||||||
|
static struct cpdma_desc_pool *
|
||||||
|
cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align)
|
||||||
|
{
|
||||||
|
int bitmap_size;
|
||||||
|
struct cpdma_desc_pool *pool;
|
||||||
|
|
||||||
|
pool = kzalloc(sizeof(*pool), GFP_KERNEL);
|
||||||
|
if (!pool)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
spin_lock_init(&pool->lock);
|
||||||
|
|
||||||
|
pool->dev = dev;
|
||||||
|
pool->mem_size = size;
|
||||||
|
pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align);
|
||||||
|
pool->num_desc = size / pool->desc_size;
|
||||||
|
|
||||||
|
bitmap_size = (pool->num_desc / BITS_PER_LONG) * sizeof(long);
|
||||||
|
pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
|
||||||
|
if (!pool->bitmap)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (phys) {
|
||||||
|
pool->phys = phys;
|
||||||
|
pool->iomap = ioremap(phys, size);
|
||||||
|
} else {
|
||||||
|
pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
|
||||||
|
GFP_KERNEL);
|
||||||
|
pool->iomap = (void __force __iomem *)pool->cpumap;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pool->iomap)
|
||||||
|
return pool;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
kfree(pool->bitmap);
|
||||||
|
kfree(pool);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (!pool)
|
||||||
|
return;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&pool->lock, flags);
|
||||||
|
WARN_ON(pool->used_desc);
|
||||||
|
kfree(pool->bitmap);
|
||||||
|
if (pool->cpumap) {
|
||||||
|
dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap,
|
||||||
|
pool->phys);
|
||||||
|
} else {
|
||||||
|
iounmap(pool->iomap);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&pool->lock, flags);
|
||||||
|
kfree(pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool,
|
||||||
|
struct cpdma_desc __iomem *desc)
|
||||||
|
{
|
||||||
|
if (!desc)
|
||||||
|
return 0;
|
||||||
|
return pool->phys + (__force dma_addr_t)desc -
|
||||||
|
(__force dma_addr_t)pool->iomap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct cpdma_desc __iomem *
|
||||||
|
desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)
|
||||||
|
{
|
||||||
|
return dma ? pool->iomap + dma - pool->phys : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct cpdma_desc __iomem *
|
||||||
|
cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int index;
|
||||||
|
struct cpdma_desc __iomem *desc = NULL;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&pool->lock, flags);
|
||||||
|
|
||||||
|
index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0,
|
||||||
|
num_desc, 0);
|
||||||
|
if (index < pool->num_desc) {
|
||||||
|
bitmap_set(pool->bitmap, index, num_desc);
|
||||||
|
desc = pool->iomap + pool->desc_size * index;
|
||||||
|
pool->used_desc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&pool->lock, flags);
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpdma_desc_free(struct cpdma_desc_pool *pool,
|
||||||
|
struct cpdma_desc __iomem *desc, int num_desc)
|
||||||
|
{
|
||||||
|
unsigned long flags, index;
|
||||||
|
|
||||||
|
index = ((unsigned long)desc - (unsigned long)pool->iomap) /
|
||||||
|
pool->desc_size;
|
||||||
|
spin_lock_irqsave(&pool->lock, flags);
|
||||||
|
bitmap_clear(pool->bitmap, index, num_desc);
|
||||||
|
pool->used_desc--;
|
||||||
|
spin_unlock_irqrestore(&pool->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
|
||||||
|
{
|
||||||
|
struct cpdma_ctlr *ctlr;
|
||||||
|
|
||||||
|
ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL);
|
||||||
|
if (!ctlr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ctlr->state = CPDMA_STATE_IDLE;
|
||||||
|
ctlr->params = *params;
|
||||||
|
ctlr->dev = params->dev;
|
||||||
|
spin_lock_init(&ctlr->lock);
|
||||||
|
|
||||||
|
ctlr->pool = cpdma_desc_pool_create(ctlr->dev,
|
||||||
|
ctlr->params.desc_mem_phys,
|
||||||
|
ctlr->params.desc_mem_size,
|
||||||
|
ctlr->params.desc_align);
|
||||||
|
if (!ctlr->pool) {
|
||||||
|
kfree(ctlr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS))
|
||||||
|
ctlr->num_chan = CPDMA_MAX_CHANNELS;
|
||||||
|
return ctlr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctlr->lock, flags);
|
||||||
|
if (ctlr->state != CPDMA_STATE_IDLE) {
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctlr->params.has_soft_reset) {
|
||||||
|
unsigned long timeout = jiffies + HZ/10;
|
||||||
|
|
||||||
|
dma_reg_write(ctlr, CPDMA_SOFTRESET, 1);
|
||||||
|
while (time_before(jiffies, timeout)) {
|
||||||
|
if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WARN_ON(!time_before(jiffies, timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ctlr->num_chan; i++) {
|
||||||
|
__raw_writel(0, ctlr->params.txhdp + 4 * i);
|
||||||
|
__raw_writel(0, ctlr->params.rxhdp + 4 * i);
|
||||||
|
__raw_writel(0, ctlr->params.txcp + 4 * i);
|
||||||
|
__raw_writel(0, ctlr->params.rxcp + 4 * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
|
||||||
|
dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
|
||||||
|
|
||||||
|
dma_reg_write(ctlr, CPDMA_TXCONTROL, 1);
|
||||||
|
dma_reg_write(ctlr, CPDMA_RXCONTROL, 1);
|
||||||
|
|
||||||
|
ctlr->state = CPDMA_STATE_ACTIVE;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
|
||||||
|
if (ctlr->channels[i])
|
||||||
|
cpdma_chan_start(ctlr->channels[i]);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctlr->lock, flags);
|
||||||
|
if (ctlr->state != CPDMA_STATE_ACTIVE) {
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctlr->state = CPDMA_STATE_TEARDOWN;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
|
||||||
|
if (ctlr->channels[i])
|
||||||
|
cpdma_chan_stop(ctlr->channels[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
|
||||||
|
dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
|
||||||
|
|
||||||
|
dma_reg_write(ctlr, CPDMA_TXCONTROL, 0);
|
||||||
|
dma_reg_write(ctlr, CPDMA_RXCONTROL, 0);
|
||||||
|
|
||||||
|
ctlr->state = CPDMA_STATE_IDLE;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr)
|
||||||
|
{
|
||||||
|
struct device *dev = ctlr->dev;
|
||||||
|
unsigned long flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctlr->lock, flags);
|
||||||
|
|
||||||
|
dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]);
|
||||||
|
|
||||||
|
dev_info(dev, "CPDMA: txidver: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_TXIDVER));
|
||||||
|
dev_info(dev, "CPDMA: txcontrol: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_TXCONTROL));
|
||||||
|
dev_info(dev, "CPDMA: txteardown: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_TXTEARDOWN));
|
||||||
|
dev_info(dev, "CPDMA: rxidver: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_RXIDVER));
|
||||||
|
dev_info(dev, "CPDMA: rxcontrol: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_RXCONTROL));
|
||||||
|
dev_info(dev, "CPDMA: softreset: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_SOFTRESET));
|
||||||
|
dev_info(dev, "CPDMA: rxteardown: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_RXTEARDOWN));
|
||||||
|
dev_info(dev, "CPDMA: txintstatraw: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_TXINTSTATRAW));
|
||||||
|
dev_info(dev, "CPDMA: txintstatmasked: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED));
|
||||||
|
dev_info(dev, "CPDMA: txintmaskset: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_TXINTMASKSET));
|
||||||
|
dev_info(dev, "CPDMA: txintmaskclear: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR));
|
||||||
|
dev_info(dev, "CPDMA: macinvector: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_MACINVECTOR));
|
||||||
|
dev_info(dev, "CPDMA: maceoivector: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_MACEOIVECTOR));
|
||||||
|
dev_info(dev, "CPDMA: rxintstatraw: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_RXINTSTATRAW));
|
||||||
|
dev_info(dev, "CPDMA: rxintstatmasked: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED));
|
||||||
|
dev_info(dev, "CPDMA: rxintmaskset: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_RXINTMASKSET));
|
||||||
|
dev_info(dev, "CPDMA: rxintmaskclear: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR));
|
||||||
|
dev_info(dev, "CPDMA: dmaintstatraw: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW));
|
||||||
|
dev_info(dev, "CPDMA: dmaintstatmasked: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED));
|
||||||
|
dev_info(dev, "CPDMA: dmaintmaskset: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_DMAINTMASKSET));
|
||||||
|
dev_info(dev, "CPDMA: dmaintmaskclear: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR));
|
||||||
|
|
||||||
|
if (!ctlr->params.has_ext_regs) {
|
||||||
|
dev_info(dev, "CPDMA: dmacontrol: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_DMACONTROL));
|
||||||
|
dev_info(dev, "CPDMA: dmastatus: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_DMASTATUS));
|
||||||
|
dev_info(dev, "CPDMA: rxbuffofs: %x",
|
||||||
|
dma_reg_read(ctlr, CPDMA_RXBUFFOFS));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++)
|
||||||
|
if (ctlr->channels[i])
|
||||||
|
cpdma_chan_dump(ctlr->channels[i]);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int ret = 0, i;
|
||||||
|
|
||||||
|
if (!ctlr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctlr->lock, flags);
|
||||||
|
if (ctlr->state != CPDMA_STATE_IDLE)
|
||||||
|
cpdma_ctlr_stop(ctlr);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
|
||||||
|
if (ctlr->channels[i])
|
||||||
|
cpdma_chan_destroy(ctlr->channels[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
cpdma_desc_pool_destroy(ctlr->pool);
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
kfree(ctlr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int i, reg;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctlr->lock, flags);
|
||||||
|
if (ctlr->state != CPDMA_STATE_ACTIVE) {
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR;
|
||||||
|
dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
|
||||||
|
if (ctlr->channels[i])
|
||||||
|
cpdma_chan_int_ctrl(ctlr->channels[i], enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr)
|
||||||
|
{
|
||||||
|
dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
|
||||||
|
cpdma_handler_fn handler)
|
||||||
|
{
|
||||||
|
struct cpdma_chan *chan;
|
||||||
|
int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (__chan_linear(chan_num) >= ctlr->num_chan)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = -ENOMEM;
|
||||||
|
chan = kzalloc(sizeof(*chan), GFP_KERNEL);
|
||||||
|
if (!chan)
|
||||||
|
goto err_chan_alloc;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctlr->lock, flags);
|
||||||
|
ret = -EBUSY;
|
||||||
|
if (ctlr->channels[chan_num])
|
||||||
|
goto err_chan_busy;
|
||||||
|
|
||||||
|
chan->ctlr = ctlr;
|
||||||
|
chan->state = CPDMA_STATE_IDLE;
|
||||||
|
chan->chan_num = chan_num;
|
||||||
|
chan->handler = handler;
|
||||||
|
|
||||||
|
if (is_rx_chan(chan)) {
|
||||||
|
chan->hdp = ctlr->params.rxhdp + offset;
|
||||||
|
chan->cp = ctlr->params.rxcp + offset;
|
||||||
|
chan->rxfree = ctlr->params.rxfree + offset;
|
||||||
|
chan->int_set = CPDMA_RXINTMASKSET;
|
||||||
|
chan->int_clear = CPDMA_RXINTMASKCLEAR;
|
||||||
|
chan->td = CPDMA_RXTEARDOWN;
|
||||||
|
chan->dir = DMA_FROM_DEVICE;
|
||||||
|
} else {
|
||||||
|
chan->hdp = ctlr->params.txhdp + offset;
|
||||||
|
chan->cp = ctlr->params.txcp + offset;
|
||||||
|
chan->int_set = CPDMA_TXINTMASKSET;
|
||||||
|
chan->int_clear = CPDMA_TXINTMASKCLEAR;
|
||||||
|
chan->td = CPDMA_TXTEARDOWN;
|
||||||
|
chan->dir = DMA_TO_DEVICE;
|
||||||
|
}
|
||||||
|
chan->mask = BIT(chan_linear(chan));
|
||||||
|
|
||||||
|
spin_lock_init(&chan->lock);
|
||||||
|
|
||||||
|
ctlr->channels[chan_num] = chan;
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return chan;
|
||||||
|
|
||||||
|
err_chan_busy:
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
kfree(chan);
|
||||||
|
err_chan_alloc:
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_chan_destroy(struct cpdma_chan *chan)
|
||||||
|
{
|
||||||
|
struct cpdma_ctlr *ctlr = chan->ctlr;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (!chan)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctlr->lock, flags);
|
||||||
|
if (chan->state != CPDMA_STATE_IDLE)
|
||||||
|
cpdma_chan_stop(chan);
|
||||||
|
ctlr->channels[chan->chan_num] = NULL;
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
kfree(chan);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_chan_get_stats(struct cpdma_chan *chan,
|
||||||
|
struct cpdma_chan_stats *stats)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
if (!chan)
|
||||||
|
return -EINVAL;
|
||||||
|
spin_lock_irqsave(&chan->lock, flags);
|
||||||
|
memcpy(stats, &chan->stats, sizeof(*stats));
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_chan_dump(struct cpdma_chan *chan)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct device *dev = chan->ctlr->dev;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&chan->lock, flags);
|
||||||
|
|
||||||
|
dev_info(dev, "channel %d (%s %d) state %s",
|
||||||
|
chan->chan_num, is_rx_chan(chan) ? "rx" : "tx",
|
||||||
|
chan_linear(chan), cpdma_state_str[chan->state]);
|
||||||
|
dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp));
|
||||||
|
dev_info(dev, "\tcp: %x\n", chan_read(chan, cp));
|
||||||
|
if (chan->rxfree) {
|
||||||
|
dev_info(dev, "\trxfree: %x\n",
|
||||||
|
chan_read(chan, rxfree));
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(dev, "\tstats head_enqueue: %d\n",
|
||||||
|
chan->stats.head_enqueue);
|
||||||
|
dev_info(dev, "\tstats tail_enqueue: %d\n",
|
||||||
|
chan->stats.tail_enqueue);
|
||||||
|
dev_info(dev, "\tstats pad_enqueue: %d\n",
|
||||||
|
chan->stats.pad_enqueue);
|
||||||
|
dev_info(dev, "\tstats misqueued: %d\n",
|
||||||
|
chan->stats.misqueued);
|
||||||
|
dev_info(dev, "\tstats desc_alloc_fail: %d\n",
|
||||||
|
chan->stats.desc_alloc_fail);
|
||||||
|
dev_info(dev, "\tstats pad_alloc_fail: %d\n",
|
||||||
|
chan->stats.pad_alloc_fail);
|
||||||
|
dev_info(dev, "\tstats runt_receive_buff: %d\n",
|
||||||
|
chan->stats.runt_receive_buff);
|
||||||
|
dev_info(dev, "\tstats runt_transmit_buff: %d\n",
|
||||||
|
chan->stats.runt_transmit_buff);
|
||||||
|
dev_info(dev, "\tstats empty_dequeue: %d\n",
|
||||||
|
chan->stats.empty_dequeue);
|
||||||
|
dev_info(dev, "\tstats busy_dequeue: %d\n",
|
||||||
|
chan->stats.busy_dequeue);
|
||||||
|
dev_info(dev, "\tstats good_dequeue: %d\n",
|
||||||
|
chan->stats.good_dequeue);
|
||||||
|
dev_info(dev, "\tstats requeue: %d\n",
|
||||||
|
chan->stats.requeue);
|
||||||
|
dev_info(dev, "\tstats teardown_dequeue: %d\n",
|
||||||
|
chan->stats.teardown_dequeue);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cpdma_chan_submit(struct cpdma_chan *chan,
|
||||||
|
struct cpdma_desc __iomem *desc)
|
||||||
|
{
|
||||||
|
struct cpdma_ctlr *ctlr = chan->ctlr;
|
||||||
|
struct cpdma_desc __iomem *prev = chan->tail;
|
||||||
|
struct cpdma_desc_pool *pool = ctlr->pool;
|
||||||
|
dma_addr_t desc_dma;
|
||||||
|
u32 mode;
|
||||||
|
|
||||||
|
desc_dma = desc_phys(pool, desc);
|
||||||
|
|
||||||
|
/* simple case - idle channel */
|
||||||
|
if (!chan->head) {
|
||||||
|
chan->stats.head_enqueue++;
|
||||||
|
chan->head = desc;
|
||||||
|
chan->tail = desc;
|
||||||
|
if (chan->state == CPDMA_STATE_ACTIVE)
|
||||||
|
chan_write(chan, hdp, desc_dma);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first chain the descriptor at the tail of the list */
|
||||||
|
desc_write(prev, hw_next, desc_dma);
|
||||||
|
chan->tail = desc;
|
||||||
|
chan->stats.tail_enqueue++;
|
||||||
|
|
||||||
|
/* next check if EOQ has been triggered already */
|
||||||
|
mode = desc_read(prev, hw_mode);
|
||||||
|
if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) &&
|
||||||
|
(chan->state == CPDMA_STATE_ACTIVE)) {
|
||||||
|
desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ);
|
||||||
|
chan_write(chan, hdp, desc_dma);
|
||||||
|
chan->stats.misqueued++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
|
||||||
|
int len, gfp_t gfp_mask)
|
||||||
|
{
|
||||||
|
struct cpdma_ctlr *ctlr = chan->ctlr;
|
||||||
|
struct cpdma_desc __iomem *desc;
|
||||||
|
dma_addr_t buffer;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 mode;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&chan->lock, flags);
|
||||||
|
|
||||||
|
if (chan->state == CPDMA_STATE_TEARDOWN) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto unlock_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc = cpdma_desc_alloc(ctlr->pool, 1);
|
||||||
|
if (!desc) {
|
||||||
|
chan->stats.desc_alloc_fail++;
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto unlock_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < ctlr->params.min_packet_size) {
|
||||||
|
len = ctlr->params.min_packet_size;
|
||||||
|
chan->stats.runt_transmit_buff++;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
|
||||||
|
mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
|
||||||
|
|
||||||
|
desc_write(desc, hw_next, 0);
|
||||||
|
desc_write(desc, hw_buffer, buffer);
|
||||||
|
desc_write(desc, hw_len, len);
|
||||||
|
desc_write(desc, hw_mode, mode | len);
|
||||||
|
desc_write(desc, sw_token, token);
|
||||||
|
desc_write(desc, sw_buffer, buffer);
|
||||||
|
desc_write(desc, sw_len, len);
|
||||||
|
|
||||||
|
__cpdma_chan_submit(chan, desc);
|
||||||
|
|
||||||
|
if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree)
|
||||||
|
chan_write(chan, rxfree, 1);
|
||||||
|
|
||||||
|
chan->count++;
|
||||||
|
|
||||||
|
unlock_ret:
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cpdma_chan_free(struct cpdma_chan *chan,
|
||||||
|
struct cpdma_desc __iomem *desc,
|
||||||
|
int outlen, int status)
|
||||||
|
{
|
||||||
|
struct cpdma_ctlr *ctlr = chan->ctlr;
|
||||||
|
struct cpdma_desc_pool *pool = ctlr->pool;
|
||||||
|
dma_addr_t buff_dma;
|
||||||
|
int origlen;
|
||||||
|
void *token;
|
||||||
|
|
||||||
|
token = (void *)desc_read(desc, sw_token);
|
||||||
|
buff_dma = desc_read(desc, sw_buffer);
|
||||||
|
origlen = desc_read(desc, sw_len);
|
||||||
|
|
||||||
|
dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
|
||||||
|
cpdma_desc_free(pool, desc, 1);
|
||||||
|
(*chan->handler)(token, outlen, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cpdma_chan_process(struct cpdma_chan *chan)
|
||||||
|
{
|
||||||
|
struct cpdma_ctlr *ctlr = chan->ctlr;
|
||||||
|
struct cpdma_desc __iomem *desc;
|
||||||
|
int status, outlen;
|
||||||
|
struct cpdma_desc_pool *pool = ctlr->pool;
|
||||||
|
dma_addr_t desc_dma;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&chan->lock, flags);
|
||||||
|
|
||||||
|
desc = chan->head;
|
||||||
|
if (!desc) {
|
||||||
|
chan->stats.empty_dequeue++;
|
||||||
|
status = -ENOENT;
|
||||||
|
goto unlock_ret;
|
||||||
|
}
|
||||||
|
desc_dma = desc_phys(pool, desc);
|
||||||
|
|
||||||
|
status = __raw_readl(&desc->hw_mode);
|
||||||
|
outlen = status & 0x7ff;
|
||||||
|
if (status & CPDMA_DESC_OWNER) {
|
||||||
|
chan->stats.busy_dequeue++;
|
||||||
|
status = -EBUSY;
|
||||||
|
goto unlock_ret;
|
||||||
|
}
|
||||||
|
status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
|
||||||
|
|
||||||
|
chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
|
||||||
|
chan_write(chan, cp, desc_dma);
|
||||||
|
chan->count--;
|
||||||
|
chan->stats.good_dequeue++;
|
||||||
|
|
||||||
|
if (status & CPDMA_DESC_EOQ) {
|
||||||
|
chan->stats.requeue++;
|
||||||
|
chan_write(chan, hdp, desc_phys(pool, chan->head));
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
|
||||||
|
__cpdma_chan_free(chan, desc, outlen, status);
|
||||||
|
return status;
|
||||||
|
|
||||||
|
unlock_ret:
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_chan_process(struct cpdma_chan *chan, int quota)
|
||||||
|
{
|
||||||
|
int used = 0, ret = 0;
|
||||||
|
|
||||||
|
if (chan->state != CPDMA_STATE_ACTIVE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
while (used < quota) {
|
||||||
|
ret = __cpdma_chan_process(chan);
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
used++;
|
||||||
|
}
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_chan_start(struct cpdma_chan *chan)
|
||||||
|
{
|
||||||
|
struct cpdma_ctlr *ctlr = chan->ctlr;
|
||||||
|
struct cpdma_desc_pool *pool = ctlr->pool;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&chan->lock, flags);
|
||||||
|
if (chan->state != CPDMA_STATE_IDLE) {
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
if (ctlr->state != CPDMA_STATE_ACTIVE) {
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
dma_reg_write(ctlr, chan->int_set, chan->mask);
|
||||||
|
chan->state = CPDMA_STATE_ACTIVE;
|
||||||
|
if (chan->head) {
|
||||||
|
chan_write(chan, hdp, desc_phys(pool, chan->head));
|
||||||
|
if (chan->rxfree)
|
||||||
|
chan_write(chan, rxfree, chan->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_chan_stop(struct cpdma_chan *chan)
|
||||||
|
{
|
||||||
|
struct cpdma_ctlr *ctlr = chan->ctlr;
|
||||||
|
struct cpdma_desc_pool *pool = ctlr->pool;
|
||||||
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
unsigned long timeout;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&chan->lock, flags);
|
||||||
|
if (chan->state != CPDMA_STATE_ACTIVE) {
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
chan->state = CPDMA_STATE_TEARDOWN;
|
||||||
|
dma_reg_write(ctlr, chan->int_clear, chan->mask);
|
||||||
|
|
||||||
|
/* trigger teardown */
|
||||||
|
dma_reg_write(ctlr, chan->td, chan->chan_num);
|
||||||
|
|
||||||
|
/* wait for teardown complete */
|
||||||
|
timeout = jiffies + HZ/10; /* 100 msec */
|
||||||
|
while (time_before(jiffies, timeout)) {
|
||||||
|
u32 cp = chan_read(chan, cp);
|
||||||
|
if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE)
|
||||||
|
break;
|
||||||
|
cpu_relax();
|
||||||
|
}
|
||||||
|
WARN_ON(!time_before(jiffies, timeout));
|
||||||
|
chan_write(chan, cp, CPDMA_TEARDOWN_VALUE);
|
||||||
|
|
||||||
|
/* handle completed packets */
|
||||||
|
do {
|
||||||
|
ret = __cpdma_chan_process(chan);
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
} while ((ret & CPDMA_DESC_TD_COMPLETE) == 0);
|
||||||
|
|
||||||
|
/* remaining packets haven't been tx/rx'ed, clean them up */
|
||||||
|
while (chan->head) {
|
||||||
|
struct cpdma_desc __iomem *desc = chan->head;
|
||||||
|
dma_addr_t next_dma;
|
||||||
|
|
||||||
|
next_dma = desc_read(desc, hw_next);
|
||||||
|
chan->head = desc_from_phys(pool, next_dma);
|
||||||
|
chan->stats.teardown_dequeue++;
|
||||||
|
|
||||||
|
/* issue callback without locks held */
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
__cpdma_chan_free(chan, desc, 0, -ENOSYS);
|
||||||
|
spin_lock_irqsave(&chan->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
chan->state = CPDMA_STATE_IDLE;
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&chan->lock, flags);
|
||||||
|
if (chan->state != CPDMA_STATE_ACTIVE) {
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear,
|
||||||
|
chan->mask);
|
||||||
|
spin_unlock_irqrestore(&chan->lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cpdma_control_info {
|
||||||
|
u32 reg;
|
||||||
|
u32 shift, mask;
|
||||||
|
int access;
|
||||||
|
#define ACCESS_RO BIT(0)
|
||||||
|
#define ACCESS_WO BIT(1)
|
||||||
|
#define ACCESS_RW (ACCESS_RO | ACCESS_WO)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpdma_control_info controls[] = {
|
||||||
|
[CPDMA_CMD_IDLE] = {CPDMA_DMACONTROL, 3, 1, ACCESS_WO},
|
||||||
|
[CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL, 4, 1, ACCESS_RW},
|
||||||
|
[CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL, 2, 1, ACCESS_RW},
|
||||||
|
[CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL, 1, 1, ACCESS_RW},
|
||||||
|
[CPDMA_TX_PRIO_FIXED] = {CPDMA_DMACONTROL, 0, 1, ACCESS_RW},
|
||||||
|
[CPDMA_STAT_IDLE] = {CPDMA_DMASTATUS, 31, 1, ACCESS_RO},
|
||||||
|
[CPDMA_STAT_TX_ERR_CODE] = {CPDMA_DMASTATUS, 20, 0xf, ACCESS_RW},
|
||||||
|
[CPDMA_STAT_TX_ERR_CHAN] = {CPDMA_DMASTATUS, 16, 0x7, ACCESS_RW},
|
||||||
|
[CPDMA_STAT_RX_ERR_CODE] = {CPDMA_DMASTATUS, 12, 0xf, ACCESS_RW},
|
||||||
|
[CPDMA_STAT_RX_ERR_CHAN] = {CPDMA_DMASTATUS, 8, 0x7, ACCESS_RW},
|
||||||
|
[CPDMA_RX_BUFFER_OFFSET] = {CPDMA_RXBUFFOFS, 0, 0xffff, ACCESS_RW},
|
||||||
|
};
|
||||||
|
|
||||||
|
int cpdma_control_get(struct cpdma_ctlr *ctlr, int control)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct cpdma_control_info *info = &controls[control];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctlr->lock, flags);
|
||||||
|
|
||||||
|
ret = -ENOTSUPP;
|
||||||
|
if (!ctlr->params.has_ext_regs)
|
||||||
|
goto unlock_ret;
|
||||||
|
|
||||||
|
ret = -EINVAL;
|
||||||
|
if (ctlr->state != CPDMA_STATE_ACTIVE)
|
||||||
|
goto unlock_ret;
|
||||||
|
|
||||||
|
ret = -ENOENT;
|
||||||
|
if (control < 0 || control >= ARRAY_SIZE(controls))
|
||||||
|
goto unlock_ret;
|
||||||
|
|
||||||
|
ret = -EPERM;
|
||||||
|
if ((info->access & ACCESS_RO) != ACCESS_RO)
|
||||||
|
goto unlock_ret;
|
||||||
|
|
||||||
|
ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask;
|
||||||
|
|
||||||
|
unlock_ret:
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
struct cpdma_control_info *info = &controls[control];
|
||||||
|
int ret;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctlr->lock, flags);
|
||||||
|
|
||||||
|
ret = -ENOTSUPP;
|
||||||
|
if (!ctlr->params.has_ext_regs)
|
||||||
|
goto unlock_ret;
|
||||||
|
|
||||||
|
ret = -EINVAL;
|
||||||
|
if (ctlr->state != CPDMA_STATE_ACTIVE)
|
||||||
|
goto unlock_ret;
|
||||||
|
|
||||||
|
ret = -ENOENT;
|
||||||
|
if (control < 0 || control >= ARRAY_SIZE(controls))
|
||||||
|
goto unlock_ret;
|
||||||
|
|
||||||
|
ret = -EPERM;
|
||||||
|
if ((info->access & ACCESS_WO) != ACCESS_WO)
|
||||||
|
goto unlock_ret;
|
||||||
|
|
||||||
|
val = dma_reg_read(ctlr, info->reg);
|
||||||
|
val &= ~(info->mask << info->shift);
|
||||||
|
val |= (value & info->mask) << info->shift;
|
||||||
|
dma_reg_write(ctlr, info->reg, val);
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
unlock_ret:
|
||||||
|
spin_unlock_irqrestore(&ctlr->lock, flags);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Texas Instruments CPDMA Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Texas Instruments
|
||||||
|
*
|
||||||
|
* 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 version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||||
|
* kind, whether express or implied; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#ifndef __DAVINCI_CPDMA_H__
|
||||||
|
#define __DAVINCI_CPDMA_H__
|
||||||
|
|
||||||
|
#define CPDMA_MAX_CHANNELS BITS_PER_LONG
|
||||||
|
|
||||||
|
#define tx_chan_num(chan) (chan)
|
||||||
|
#define rx_chan_num(chan) ((chan) + CPDMA_MAX_CHANNELS)
|
||||||
|
#define is_rx_chan(chan) ((chan)->chan_num >= CPDMA_MAX_CHANNELS)
|
||||||
|
#define is_tx_chan(chan) (!is_rx_chan(chan))
|
||||||
|
#define __chan_linear(chan_num) ((chan_num) & (CPDMA_MAX_CHANNELS - 1))
|
||||||
|
#define chan_linear(chan) __chan_linear((chan)->chan_num)
|
||||||
|
|
||||||
|
struct cpdma_params {
|
||||||
|
struct device *dev;
|
||||||
|
void __iomem *dmaregs;
|
||||||
|
void __iomem *txhdp, *rxhdp, *txcp, *rxcp;
|
||||||
|
void __iomem *rxthresh, *rxfree;
|
||||||
|
int num_chan;
|
||||||
|
bool has_soft_reset;
|
||||||
|
int min_packet_size;
|
||||||
|
u32 desc_mem_phys;
|
||||||
|
int desc_mem_size;
|
||||||
|
int desc_align;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some instances of embedded cpdma controllers have extra control and
|
||||||
|
* status registers. The following flag enables access to these
|
||||||
|
* "extended" registers.
|
||||||
|
*/
|
||||||
|
bool has_ext_regs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpdma_chan_stats {
|
||||||
|
u32 head_enqueue;
|
||||||
|
u32 tail_enqueue;
|
||||||
|
u32 pad_enqueue;
|
||||||
|
u32 misqueued;
|
||||||
|
u32 desc_alloc_fail;
|
||||||
|
u32 pad_alloc_fail;
|
||||||
|
u32 runt_receive_buff;
|
||||||
|
u32 runt_transmit_buff;
|
||||||
|
u32 empty_dequeue;
|
||||||
|
u32 busy_dequeue;
|
||||||
|
u32 good_dequeue;
|
||||||
|
u32 requeue;
|
||||||
|
u32 teardown_dequeue;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpdma_ctlr;
|
||||||
|
struct cpdma_chan;
|
||||||
|
|
||||||
|
typedef void (*cpdma_handler_fn)(void *token, int len, int status);
|
||||||
|
|
||||||
|
struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params);
|
||||||
|
int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr);
|
||||||
|
int cpdma_ctlr_start(struct cpdma_ctlr *ctlr);
|
||||||
|
int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr);
|
||||||
|
int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr);
|
||||||
|
|
||||||
|
struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
|
||||||
|
cpdma_handler_fn handler);
|
||||||
|
int cpdma_chan_destroy(struct cpdma_chan *chan);
|
||||||
|
int cpdma_chan_start(struct cpdma_chan *chan);
|
||||||
|
int cpdma_chan_stop(struct cpdma_chan *chan);
|
||||||
|
int cpdma_chan_dump(struct cpdma_chan *chan);
|
||||||
|
|
||||||
|
int cpdma_chan_get_stats(struct cpdma_chan *chan,
|
||||||
|
struct cpdma_chan_stats *stats);
|
||||||
|
int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
|
||||||
|
int len, gfp_t gfp_mask);
|
||||||
|
int cpdma_chan_process(struct cpdma_chan *chan, int quota);
|
||||||
|
|
||||||
|
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
|
||||||
|
void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr);
|
||||||
|
int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
|
||||||
|
|
||||||
|
enum cpdma_control {
|
||||||
|
CPDMA_CMD_IDLE, /* write-only */
|
||||||
|
CPDMA_COPY_ERROR_FRAMES, /* read-write */
|
||||||
|
CPDMA_RX_OFF_LEN_UPDATE, /* read-write */
|
||||||
|
CPDMA_RX_OWNERSHIP_FLIP, /* read-write */
|
||||||
|
CPDMA_TX_PRIO_FIXED, /* read-write */
|
||||||
|
CPDMA_STAT_IDLE, /* read-only */
|
||||||
|
CPDMA_STAT_TX_ERR_CHAN, /* read-only */
|
||||||
|
CPDMA_STAT_TX_ERR_CODE, /* read-only */
|
||||||
|
CPDMA_STAT_RX_ERR_CHAN, /* read-only */
|
||||||
|
CPDMA_STAT_RX_ERR_CODE, /* read-only */
|
||||||
|
CPDMA_RX_BUFFER_OFFSET, /* read-write */
|
||||||
|
};
|
||||||
|
|
||||||
|
int cpdma_control_get(struct cpdma_ctlr *ctlr, int control);
|
||||||
|
int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value);
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,475 @@
|
||||||
|
/*
|
||||||
|
* DaVinci MDIO Module driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Texas Instruments.
|
||||||
|
*
|
||||||
|
* Shamelessly ripped out of davinci_emac.c, original copyrights follow:
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Texas Instruments.
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
* ---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/davinci_emac.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This timeout definition is a worst-case ultra defensive measure against
|
||||||
|
* unexpected controller lock ups. Ideally, we should never ever hit this
|
||||||
|
* scenario in practice.
|
||||||
|
*/
|
||||||
|
#define MDIO_TIMEOUT 100 /* msecs */
|
||||||
|
|
||||||
|
#define PHY_REG_MASK 0x1f
|
||||||
|
#define PHY_ID_MASK 0x1f
|
||||||
|
|
||||||
|
#define DEF_OUT_FREQ 2200000 /* 2.2 MHz */
|
||||||
|
|
||||||
|
struct davinci_mdio_regs {
|
||||||
|
u32 version;
|
||||||
|
u32 control;
|
||||||
|
#define CONTROL_IDLE BIT(31)
|
||||||
|
#define CONTROL_ENABLE BIT(30)
|
||||||
|
#define CONTROL_MAX_DIV (0xff)
|
||||||
|
|
||||||
|
u32 alive;
|
||||||
|
u32 link;
|
||||||
|
u32 linkintraw;
|
||||||
|
u32 linkintmasked;
|
||||||
|
u32 __reserved_0[2];
|
||||||
|
u32 userintraw;
|
||||||
|
u32 userintmasked;
|
||||||
|
u32 userintmaskset;
|
||||||
|
u32 userintmaskclr;
|
||||||
|
u32 __reserved_1[20];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u32 access;
|
||||||
|
#define USERACCESS_GO BIT(31)
|
||||||
|
#define USERACCESS_WRITE BIT(30)
|
||||||
|
#define USERACCESS_ACK BIT(29)
|
||||||
|
#define USERACCESS_READ (0)
|
||||||
|
#define USERACCESS_DATA (0xffff)
|
||||||
|
|
||||||
|
u32 physel;
|
||||||
|
} user[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mdio_platform_data default_pdata = {
|
||||||
|
.bus_freq = DEF_OUT_FREQ,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct davinci_mdio_data {
|
||||||
|
struct mdio_platform_data pdata;
|
||||||
|
struct davinci_mdio_regs __iomem *regs;
|
||||||
|
spinlock_t lock;
|
||||||
|
struct clk *clk;
|
||||||
|
struct device *dev;
|
||||||
|
struct mii_bus *bus;
|
||||||
|
bool suspended;
|
||||||
|
unsigned long access_time; /* jiffies */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __davinci_mdio_reset(struct davinci_mdio_data *data)
|
||||||
|
{
|
||||||
|
u32 mdio_in, div, mdio_out_khz, access_time;
|
||||||
|
|
||||||
|
mdio_in = clk_get_rate(data->clk);
|
||||||
|
div = (mdio_in / data->pdata.bus_freq) - 1;
|
||||||
|
if (div > CONTROL_MAX_DIV)
|
||||||
|
div = CONTROL_MAX_DIV;
|
||||||
|
|
||||||
|
/* set enable and clock divider */
|
||||||
|
__raw_writel(div | CONTROL_ENABLE, &data->regs->control);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One mdio transaction consists of:
|
||||||
|
* 32 bits of preamble
|
||||||
|
* 32 bits of transferred data
|
||||||
|
* 24 bits of bus yield (not needed unless shared?)
|
||||||
|
*/
|
||||||
|
mdio_out_khz = mdio_in / (1000 * (div + 1));
|
||||||
|
access_time = (88 * 1000) / mdio_out_khz;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the worst case, we could be kicking off a user-access immediately
|
||||||
|
* after the mdio bus scan state-machine triggered its own read. If
|
||||||
|
* so, our request could get deferred by one access cycle. We
|
||||||
|
* defensively allow for 4 access cycles.
|
||||||
|
*/
|
||||||
|
data->access_time = usecs_to_jiffies(access_time * 4);
|
||||||
|
if (!data->access_time)
|
||||||
|
data->access_time = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int davinci_mdio_reset(struct mii_bus *bus)
|
||||||
|
{
|
||||||
|
struct davinci_mdio_data *data = bus->priv;
|
||||||
|
u32 phy_mask, ver;
|
||||||
|
|
||||||
|
__davinci_mdio_reset(data);
|
||||||
|
|
||||||
|
/* wait for scan logic to settle */
|
||||||
|
msleep(PHY_MAX_ADDR * data->access_time);
|
||||||
|
|
||||||
|
/* dump hardware version info */
|
||||||
|
ver = __raw_readl(&data->regs->version);
|
||||||
|
dev_info(data->dev, "davinci mdio revision %d.%d\n",
|
||||||
|
(ver >> 8) & 0xff, ver & 0xff);
|
||||||
|
|
||||||
|
/* get phy mask from the alive register */
|
||||||
|
phy_mask = __raw_readl(&data->regs->alive);
|
||||||
|
if (phy_mask) {
|
||||||
|
/* restrict mdio bus to live phys only */
|
||||||
|
dev_info(data->dev, "detected phy mask %x\n", ~phy_mask);
|
||||||
|
phy_mask = ~phy_mask;
|
||||||
|
} else {
|
||||||
|
/* desperately scan all phys */
|
||||||
|
dev_warn(data->dev, "no live phy, scanning all\n");
|
||||||
|
phy_mask = 0;
|
||||||
|
}
|
||||||
|
data->bus->phy_mask = phy_mask;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait until hardware is ready for another user access */
|
||||||
|
static inline int wait_for_user_access(struct davinci_mdio_data *data)
|
||||||
|
{
|
||||||
|
struct davinci_mdio_regs __iomem *regs = data->regs;
|
||||||
|
unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
while (time_after(timeout, jiffies)) {
|
||||||
|
reg = __raw_readl(®s->user[0].access);
|
||||||
|
if ((reg & USERACCESS_GO) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
reg = __raw_readl(®s->control);
|
||||||
|
if ((reg & CONTROL_IDLE) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An emac soft_reset may have clobbered the mdio controller's
|
||||||
|
* state machine. We need to reset and retry the current
|
||||||
|
* operation
|
||||||
|
*/
|
||||||
|
dev_warn(data->dev, "resetting idled controller\n");
|
||||||
|
__davinci_mdio_reset(data);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
dev_err(data->dev, "timed out waiting for user access\n");
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait until hardware state machine is idle */
|
||||||
|
static inline int wait_for_idle(struct davinci_mdio_data *data)
|
||||||
|
{
|
||||||
|
struct davinci_mdio_regs __iomem *regs = data->regs;
|
||||||
|
unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
|
||||||
|
|
||||||
|
while (time_after(timeout, jiffies)) {
|
||||||
|
if (__raw_readl(®s->control) & CONTROL_IDLE)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dev_err(data->dev, "timed out waiting for idle\n");
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)
|
||||||
|
{
|
||||||
|
struct davinci_mdio_data *data = bus->priv;
|
||||||
|
u32 reg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
spin_lock(&data->lock);
|
||||||
|
|
||||||
|
if (data->suspended) {
|
||||||
|
spin_unlock(&data->lock);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
|
||||||
|
(phy_id << 16));
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ret = wait_for_user_access(data);
|
||||||
|
if (ret == -EAGAIN)
|
||||||
|
continue;
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
__raw_writel(reg, &data->regs->user[0].access);
|
||||||
|
|
||||||
|
ret = wait_for_user_access(data);
|
||||||
|
if (ret == -EAGAIN)
|
||||||
|
continue;
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
reg = __raw_readl(&data->regs->user[0].access);
|
||||||
|
ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&data->lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int davinci_mdio_write(struct mii_bus *bus, int phy_id,
|
||||||
|
int phy_reg, u16 phy_data)
|
||||||
|
{
|
||||||
|
struct davinci_mdio_data *data = bus->priv;
|
||||||
|
u32 reg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
spin_lock(&data->lock);
|
||||||
|
|
||||||
|
if (data->suspended) {
|
||||||
|
spin_unlock(&data->lock);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
|
||||||
|
(phy_id << 16) | (phy_data & USERACCESS_DATA));
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ret = wait_for_user_access(data);
|
||||||
|
if (ret == -EAGAIN)
|
||||||
|
continue;
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
__raw_writel(reg, &data->regs->user[0].access);
|
||||||
|
|
||||||
|
ret = wait_for_user_access(data);
|
||||||
|
if (ret == -EAGAIN)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&data->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devinit davinci_mdio_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct mdio_platform_data *pdata = pdev->dev.platform_data;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct davinci_mdio_data *data;
|
||||||
|
struct resource *res;
|
||||||
|
struct phy_device *phy;
|
||||||
|
int ret, addr;
|
||||||
|
|
||||||
|
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||||
|
if (!data) {
|
||||||
|
dev_err(dev, "failed to alloc device data\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->pdata = pdata ? (*pdata) : default_pdata;
|
||||||
|
|
||||||
|
data->bus = mdiobus_alloc();
|
||||||
|
if (!data->bus) {
|
||||||
|
dev_err(dev, "failed to alloc mii bus\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto bail_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->bus->name = dev_name(dev);
|
||||||
|
data->bus->read = davinci_mdio_read,
|
||||||
|
data->bus->write = davinci_mdio_write,
|
||||||
|
data->bus->reset = davinci_mdio_reset,
|
||||||
|
data->bus->parent = dev;
|
||||||
|
data->bus->priv = data;
|
||||||
|
snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
|
||||||
|
|
||||||
|
data->clk = clk_get(dev, NULL);
|
||||||
|
if (IS_ERR(data->clk)) {
|
||||||
|
data->clk = NULL;
|
||||||
|
dev_err(dev, "failed to get device clock\n");
|
||||||
|
ret = PTR_ERR(data->clk);
|
||||||
|
goto bail_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_enable(data->clk);
|
||||||
|
|
||||||
|
dev_set_drvdata(dev, data);
|
||||||
|
data->dev = dev;
|
||||||
|
spin_lock_init(&data->lock);
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!res) {
|
||||||
|
dev_err(dev, "could not find register map resource\n");
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto bail_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = devm_request_mem_region(dev, res->start, resource_size(res),
|
||||||
|
dev_name(dev));
|
||||||
|
if (!res) {
|
||||||
|
dev_err(dev, "could not allocate register map resource\n");
|
||||||
|
ret = -ENXIO;
|
||||||
|
goto bail_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
|
||||||
|
if (!data->regs) {
|
||||||
|
dev_err(dev, "could not map mdio registers\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto bail_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* register the mii bus */
|
||||||
|
ret = mdiobus_register(data->bus);
|
||||||
|
if (ret)
|
||||||
|
goto bail_out;
|
||||||
|
|
||||||
|
/* scan and dump the bus */
|
||||||
|
for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
|
||||||
|
phy = data->bus->phy_map[addr];
|
||||||
|
if (phy) {
|
||||||
|
dev_info(dev, "phy[%d]: device %s, driver %s\n",
|
||||||
|
phy->addr, dev_name(&phy->dev),
|
||||||
|
phy->drv ? phy->drv->name : "unknown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bail_out:
|
||||||
|
if (data->bus)
|
||||||
|
mdiobus_free(data->bus);
|
||||||
|
|
||||||
|
if (data->clk) {
|
||||||
|
clk_disable(data->clk);
|
||||||
|
clk_put(data->clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit davinci_mdio_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct davinci_mdio_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (data->bus)
|
||||||
|
mdiobus_free(data->bus);
|
||||||
|
|
||||||
|
if (data->clk) {
|
||||||
|
clk_disable(data->clk);
|
||||||
|
clk_put(data->clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_set_drvdata(dev, NULL);
|
||||||
|
|
||||||
|
kfree(data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int davinci_mdio_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct davinci_mdio_data *data = dev_get_drvdata(dev);
|
||||||
|
u32 ctrl;
|
||||||
|
|
||||||
|
spin_lock(&data->lock);
|
||||||
|
|
||||||
|
/* shutdown the scan state machine */
|
||||||
|
ctrl = __raw_readl(&data->regs->control);
|
||||||
|
ctrl &= ~CONTROL_ENABLE;
|
||||||
|
__raw_writel(ctrl, &data->regs->control);
|
||||||
|
wait_for_idle(data);
|
||||||
|
|
||||||
|
if (data->clk)
|
||||||
|
clk_disable(data->clk);
|
||||||
|
|
||||||
|
data->suspended = true;
|
||||||
|
spin_unlock(&data->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int davinci_mdio_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct davinci_mdio_data *data = dev_get_drvdata(dev);
|
||||||
|
u32 ctrl;
|
||||||
|
|
||||||
|
spin_lock(&data->lock);
|
||||||
|
if (data->clk)
|
||||||
|
clk_enable(data->clk);
|
||||||
|
|
||||||
|
/* restart the scan state machine */
|
||||||
|
ctrl = __raw_readl(&data->regs->control);
|
||||||
|
ctrl |= CONTROL_ENABLE;
|
||||||
|
__raw_writel(ctrl, &data->regs->control);
|
||||||
|
|
||||||
|
data->suspended = false;
|
||||||
|
spin_unlock(&data->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dev_pm_ops davinci_mdio_pm_ops = {
|
||||||
|
.suspend = davinci_mdio_suspend,
|
||||||
|
.resume = davinci_mdio_resume,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_driver davinci_mdio_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "davinci_mdio",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.pm = &davinci_mdio_pm_ops,
|
||||||
|
},
|
||||||
|
.probe = davinci_mdio_probe,
|
||||||
|
.remove = __devexit_p(davinci_mdio_remove),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init davinci_mdio_init(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&davinci_mdio_driver);
|
||||||
|
}
|
||||||
|
device_initcall(davinci_mdio_init);
|
||||||
|
|
||||||
|
static void __exit davinci_mdio_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&davinci_mdio_driver);
|
||||||
|
}
|
||||||
|
module_exit(davinci_mdio_exit);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_DESCRIPTION("DaVinci MDIO driver");
|
|
@ -14,16 +14,26 @@
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/memory.h>
|
#include <linux/memory.h>
|
||||||
|
|
||||||
|
struct mdio_platform_data {
|
||||||
|
unsigned long bus_freq;
|
||||||
|
};
|
||||||
|
|
||||||
struct emac_platform_data {
|
struct emac_platform_data {
|
||||||
char mac_addr[ETH_ALEN];
|
char mac_addr[ETH_ALEN];
|
||||||
u32 ctrl_reg_offset;
|
u32 ctrl_reg_offset;
|
||||||
u32 ctrl_mod_reg_offset;
|
u32 ctrl_mod_reg_offset;
|
||||||
u32 ctrl_ram_offset;
|
u32 ctrl_ram_offset;
|
||||||
u32 hw_ram_addr;
|
u32 hw_ram_addr;
|
||||||
u32 mdio_reg_offset;
|
|
||||||
u32 ctrl_ram_size;
|
u32 ctrl_ram_size;
|
||||||
u32 phy_mask;
|
|
||||||
u32 mdio_max_freq;
|
/*
|
||||||
|
* phy_id can be one of the following:
|
||||||
|
* - NULL : use the first phy on the bus,
|
||||||
|
* - "" : force to 100/full, no mdio control
|
||||||
|
* - "<bus>:<addr>" : use the specified bus and phy
|
||||||
|
*/
|
||||||
|
const char *phy_id;
|
||||||
|
|
||||||
u8 rmii_en;
|
u8 rmii_en;
|
||||||
u8 version;
|
u8 version;
|
||||||
void (*interrupt_enable) (void);
|
void (*interrupt_enable) (void);
|
||||||
|
|
Loading…
Reference in New Issue