Merge branch 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci

* 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci: (40 commits)
  DaVinci DM365: Adding support for SPI EEPROM
  DaVinci DM365: Adding DM365 SPI support
  DaVinci DM355: Modifications to DM355 SPI support
  DaVinci: SPI: Adding header file for SPI support.
  davinci: dm646x: CDCE clocks: davinci_clk converted to clk_lookup
  davinci: clkdev cleanup: remove clk_lookup wrapper, use clkdev_add_table()
  DaVinci: DM365: Voice codec support for the DM365 SoC
  davinci: clock: let clk->set_rate function sleep
  Add SDA and SCL pin numbers to i2c platform data
  davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138
  davinci: build list of unused EDMA events dynamically
  davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case
  davinci: Keep count of channel controllers on a platform
  davinci: Correct return value of edma_alloc_channel api
  davinci: add CDCE949 support on DM6467 EVM
  davinci: add support for CDCE949 clock synthesizer
  davinci: da850/omap-l138 EVM: register for suspend support
  davinci: da850/omap-l138: add support for SoC suspend
  davinci: add power management support
  DaVinci: DM365: Changing default queue for DM365.
  ...
This commit is contained in:
Linus Torvalds 2010-03-01 13:05:40 -08:00
commit 13dda80e48
42 changed files with 1534 additions and 295 deletions

View File

@ -91,10 +91,14 @@ config MACH_DAVINCI_DM6467_EVM
bool "TI DM6467 EVM"
default ARCH_DAVINCI_DM646x
depends on ARCH_DAVINCI_DM646x
select MACH_DAVINCI_DM6467TEVM
help
Configure this option to specify the whether the board used
for development is a DM6467 EVM
config MACH_DAVINCI_DM6467TEVM
bool
config MACH_DAVINCI_DM365_EVM
bool "TI DM365 EVM"
default ARCH_DAVINCI_DM365

View File

@ -26,7 +26,7 @@ obj-$(CONFIG_MACH_SFFSDR) += board-sffsdr.o
obj-$(CONFIG_MACH_NEUROS_OSD2) += board-neuros-osd2.o
obj-$(CONFIG_MACH_DAVINCI_DM355_EVM) += board-dm355-evm.o
obj-$(CONFIG_MACH_DM355_LEOPARD) += board-dm355-leopard.o
obj-$(CONFIG_MACH_DAVINCI_DM6467_EVM) += board-dm646x-evm.o
obj-$(CONFIG_MACH_DAVINCI_DM6467_EVM) += board-dm646x-evm.o cdce949.o
obj-$(CONFIG_MACH_DAVINCI_DM365_EVM) += board-dm365-evm.o
obj-$(CONFIG_MACH_DAVINCI_DA830_EVM) += board-da830-evm.o
obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o
@ -34,3 +34,4 @@ obj-$(CONFIG_MACH_DAVINCI_DA850_EVM) += board-da850-evm.o
# Power Management
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_SUSPEND) += pm.o sleep.o

View File

@ -112,7 +112,7 @@ static __init void da830_evm_usb_init(void)
* Set up USB clock/mode in the CFGCHIP2 register.
* FYI: CFGCHIP2 is 0x0000ef00 initially.
*/
cfgchip2 = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP2_REG));
cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
/* USB2.0 PHY reference clock is 24 MHz */
cfgchip2 &= ~CFGCHIP2_REFFREQ;
@ -139,7 +139,7 @@ static __init void da830_evm_usb_init(void)
cfgchip2 |= CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN;
#endif
__raw_writel(cfgchip2, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP2_REG));
__raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
/* USB_REFCLKIN is not used. */
ret = davinci_cfg_reg(DA830_USB0_DRVVBUS);

View File

@ -46,8 +46,20 @@
static struct mtd_partition da850_evm_norflash_partition[] = {
{
.name = "NOR filesystem",
.name = "bootloaders + env",
.offset = 0,
.size = SZ_512K,
.mask_flags = MTD_WRITEABLE,
},
{
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = SZ_2M,
.mask_flags = 0,
},
{
.name = "filesystem",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
.mask_flags = 0,
},
@ -77,6 +89,18 @@ static struct platform_device da850_evm_norflash_device = {
.resource = da850_evm_norflash_resource,
};
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,
};
/* DA850/OMAP-L138 EVM includes a 512 MByte large-page NAND flash
* (128K blocks). It may be used instead of the (default) SPI flash
* to boot, using TI's tools to install the secondary boot loader
@ -119,6 +143,7 @@ static struct davinci_nand_pdata da850_evm_nandflash_data = {
.parts = da850_evm_nandflash_partition,
.nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition),
.ecc_mode = NAND_ECC_HW,
.ecc_bits = 4,
.options = NAND_USE_FLASH_BBT,
};
@ -537,7 +562,7 @@ static int __init da850_evm_config_emac(void)
if (!machine_is_davinci_da850_evm())
return 0;
cfg_chip3_base = DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG);
cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
val = __raw_readl(cfg_chip3_base);
@ -696,6 +721,11 @@ static __init void da850_evm_init(void)
if (ret)
pr_warning("da850_evm_init: 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

View File

@ -111,6 +111,8 @@ static struct platform_device davinci_nand_device = {
static struct davinci_i2c_platform_data i2c_pdata = {
.bus_freq = 400 /* kHz */,
.bus_delay = 0 /* usec */,
.sda_pin = 15,
.scl_pin = 14,
};
static struct snd_platform_data dm355_evm_snd_data;

View File

@ -24,6 +24,8 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/input.h>
#include <linux/spi/spi.h>
#include <linux/spi/eeprom.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -571,6 +573,24 @@ static void __init dm365_evm_map_io(void)
dm365_init();
}
static struct spi_eeprom at25640 = {
.byte_len = SZ_64K / 8,
.name = "at25640",
.page_size = 32,
.flags = EE_ADDR2,
};
static struct spi_board_info dm365_evm_spi_info[] __initconst = {
{
.modalias = "at25",
.platform_data = &at25640,
.max_speed_hz = 10 * 1000 * 1000,
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_0,
},
};
static __init void dm365_evm_init(void)
{
evm_init_i2c();
@ -587,6 +607,9 @@ static __init void dm365_evm_init(void)
dm365_init_asp(&dm365_evm_snd_data);
dm365_init_rtc();
dm365_init_ks(&dm365evm_ks_data);
dm365_init_spi0(BIT(0), dm365_evm_spi_info,
ARRAY_SIZE(dm365_evm_spi_info));
}
static __init void dm365_evm_irq_init(void)

View File

@ -629,6 +629,8 @@ static struct i2c_board_info __initdata i2c_info[] = {
static struct davinci_i2c_platform_data i2c_pdata = {
.bus_freq = 20 /* kHz */,
.bus_delay = 100 /* usec */,
.sda_pin = 44,
.scl_pin = 43,
};
static void __init evm_init_i2c(void)

View File

@ -30,6 +30,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@ -39,54 +40,13 @@
#include <mach/serial.h>
#include <mach/i2c.h>
#include <mach/nand.h>
#include <mach/clock.h>
#include <mach/cdce949.h>
#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
#define HAS_ATA 1
#else
#define HAS_ATA 0
#endif
#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x20008000
#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x42000000
#include "clock.h"
#define NAND_BLOCK_SIZE SZ_128K
/* CPLD Register 0 bits to control ATA */
#define DM646X_EVM_ATA_RST BIT(0)
#define DM646X_EVM_ATA_PWD BIT(1)
#define DM646X_EVM_PHY_MASK (0x2)
#define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */
#define VIDCLKCTL_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x38)
#define VSCLKDIS_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x6c)
#define VCH2CLK_MASK (BIT_MASK(10) | BIT_MASK(9) | BIT_MASK(8))
#define VCH2CLK_SYSCLK8 (BIT(9))
#define VCH2CLK_AUXCLK (BIT(9) | BIT(8))
#define VCH3CLK_MASK (BIT_MASK(14) | BIT_MASK(13) | BIT_MASK(12))
#define VCH3CLK_SYSCLK8 (BIT(13))
#define VCH3CLK_AUXCLK (BIT(14) | BIT(13))
#define VIDCH2CLK (BIT(10))
#define VIDCH3CLK (BIT(11))
#define VIDCH1CLK (BIT(4))
#define TVP7002_INPUT (BIT(4))
#define TVP5147_INPUT (~BIT(4))
#define VPIF_INPUT_ONE_CHANNEL (BIT(5))
#define VPIF_INPUT_TWO_CHANNEL (~BIT(5))
#define TVP5147_CH0 "tvp514x-0"
#define TVP5147_CH1 "tvp514x-1"
static void __iomem *vpif_vidclkctl_reg;
static void __iomem *vpif_vsclkdis_reg;
/* spin lock for updating above registers */
static spinlock_t vpif_reg_lock;
static struct davinci_uart_config uart_config __initdata = {
.enabled_uarts = (1 << 0),
};
/* Note: We are setting first partition as 'bootloader' constituting UBL, U-Boot
* and U-Boot environment this avoids dependency on any particular combination
* of UBL, U-Boot or flashing tools etc.
@ -120,6 +80,9 @@ static struct davinci_nand_pdata davinci_nand_data = {
.options = 0,
};
#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x20008000
#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x42000000
static struct resource davinci_nand_resources[] = {
{
.start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
@ -144,6 +107,17 @@ static struct platform_device davinci_nand_device = {
},
};
#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
#define HAS_ATA 1
#else
#define HAS_ATA 0
#endif
/* CPLD Register 0 bits to control ATA */
#define DM646X_EVM_ATA_RST BIT(0)
#define DM646X_EVM_ATA_PWD BIT(1)
/* CPLD Register 0 Client: used for I/O Control */
static int cpld_reg0_probe(struct i2c_client *client,
const struct i2c_device_id *id)
@ -417,6 +391,9 @@ static struct i2c_board_info __initdata i2c_info[] = {
{
I2C_BOARD_INFO("cpld_video", 0x3b),
},
{
I2C_BOARD_INFO("cdce949", 0x6c),
},
};
static struct davinci_i2c_platform_data i2c_pdata = {
@ -424,6 +401,30 @@ static struct davinci_i2c_platform_data i2c_pdata = {
.bus_delay = 0 /* usec */,
};
#define VIDCLKCTL_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x38)
#define VSCLKDIS_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x6c)
#define VCH2CLK_MASK (BIT_MASK(10) | BIT_MASK(9) | BIT_MASK(8))
#define VCH2CLK_SYSCLK8 (BIT(9))
#define VCH2CLK_AUXCLK (BIT(9) | BIT(8))
#define VCH3CLK_MASK (BIT_MASK(14) | BIT_MASK(13) | BIT_MASK(12))
#define VCH3CLK_SYSCLK8 (BIT(13))
#define VCH3CLK_AUXCLK (BIT(14) | BIT(13))
#define VIDCH2CLK (BIT(10))
#define VIDCH3CLK (BIT(11))
#define VIDCH1CLK (BIT(4))
#define TVP7002_INPUT (BIT(4))
#define TVP5147_INPUT (~BIT(4))
#define VPIF_INPUT_ONE_CHANNEL (BIT(5))
#define VPIF_INPUT_TWO_CHANNEL (~BIT(5))
#define TVP5147_CH0 "tvp514x-0"
#define TVP5147_CH1 "tvp514x-1"
static void __iomem *vpif_vidclkctl_reg;
static void __iomem *vpif_vsclkdis_reg;
/* spin lock for updating above registers */
static spinlock_t vpif_reg_lock;
static int set_vpif_clock(int mux_mode, int hd)
{
unsigned long flags;
@ -685,11 +686,44 @@ static void __init evm_init_i2c(void)
evm_init_video();
}
#define CDCE949_XIN_RATE 27000000
/* CDCE949 support - "lpsc" field is overridden to work as clock number */
static struct clk cdce_clk_in = {
.name = "cdce_xin",
.rate = CDCE949_XIN_RATE,
};
static struct clk_lookup cdce_clks[] = {
CLK(NULL, "xin", &cdce_clk_in),
CLK(NULL, NULL, NULL),
};
static void __init cdce_clk_init(void)
{
struct clk_lookup *c;
struct clk *clk;
for (c = cdce_clks; c->clk; c++) {
clk = c->clk;
clkdev_add(c);
clk_register(clk);
}
}
static void __init davinci_map_io(void)
{
dm646x_init();
cdce_clk_init();
}
static struct davinci_uart_config uart_config __initdata = {
.enabled_uarts = (1 << 0),
};
#define DM646X_EVM_PHY_MASK (0x2)
#define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */
static __init void evm_init(void)
{
struct davinci_soc_info *soc_info = &davinci_soc_info;
@ -713,6 +747,17 @@ static __init void davinci_dm646x_evm_irq_init(void)
davinci_irq_init();
}
#define DM646X_EVM_REF_FREQ 27000000
#define DM6467T_EVM_REF_FREQ 33000000
void __init dm646x_board_setup_refclk(struct clk *clk)
{
if (machine_is_davinci_dm6467tevm())
clk->rate = DM6467T_EVM_REF_FREQ;
else
clk->rate = DM646X_EVM_REF_FREQ;
}
MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
.phys_io = IO_PHYS,
.io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
@ -723,3 +768,13 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
.init_machine = evm_init,
MACHINE_END
MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
.phys_io = IO_PHYS,
.io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (0x80000100),
.map_io = davinci_map_io,
.init_irq = davinci_dm646x_evm_irq_init,
.timer = &davinci_timer,
.init_machine = evm_init,
MACHINE_END

View File

@ -0,0 +1,293 @@
/*
* TI CDCE949 clock synthesizer driver
*
* Note: This implementation assumes an input of 27MHz to the CDCE.
* This is by no means constrained by CDCE hardware although the datasheet
* does use this as an example for all illustrations and more importantly:
* that is the crystal input on boards it is currently used on.
*
* Copyright (C) 2009 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/clk.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <mach/clock.h>
#include "clock.h"
static struct i2c_client *cdce_i2c_client;
static DEFINE_MUTEX(cdce_mutex);
/* CDCE register descriptor */
struct cdce_reg {
u8 addr;
u8 val;
};
/* Per-Output (Y1, Y2 etc.) frequency descriptor */
struct cdce_freq {
/* Frequency in KHz */
unsigned long frequency;
/*
* List of registers to program to obtain a particular frequency.
* 0x0 in register address and value is the end of list marker.
*/
struct cdce_reg *reglist;
};
#define CDCE_FREQ_TABLE_ENTRY(line, out) \
{ \
.reglist = cdce_y ##line## _ ##out, \
.frequency = out, \
}
/* List of CDCE outputs */
struct cdce_output {
/* List of frequencies on this output */
struct cdce_freq *freq_table;
/* Number of possible frequencies */
int size;
};
/*
* Finding out the values to program into CDCE949 registers for a particular
* frequency output is not a simple calculation. Have a look at the datasheet
* for the details. There is desktop software available to help users with
* the calculations. Here, we just depend on the output of that software
* (or hand calculations) instead trying to runtime calculate the register
* values and inflicting misery on ourselves.
*/
static struct cdce_reg cdce_y1_148500[] = {
{ 0x13, 0x00 },
/* program PLL1_0 multiplier */
{ 0x18, 0xaf },
{ 0x19, 0x50 },
{ 0x1a, 0x02 },
{ 0x1b, 0xc9 },
/* program PLL1_11 multiplier */
{ 0x1c, 0x00 },
{ 0x1d, 0x40 },
{ 0x1e, 0x02 },
{ 0x1f, 0xc9 },
/* output state selection */
{ 0x15, 0x00 },
{ 0x14, 0xef },
/* switch MUX to PLL1 output */
{ 0x14, 0x6f },
{ 0x16, 0x06 },
/* set P2DIV divider, P3DIV and input crystal */
{ 0x17, 0x06 },
{ 0x01, 0x00 },
{ 0x05, 0x48 },
{ 0x02, 0x80 },
/* enable and disable PLL */
{ 0x02, 0xbc },
{ 0x03, 0x01 },
{ },
};
static struct cdce_reg cdce_y1_74250[] = {
{ 0x13, 0x00 },
{ 0x18, 0xaf },
{ 0x19, 0x50 },
{ 0x1a, 0x02 },
{ 0x1b, 0xc9 },
{ 0x1c, 0x00 },
{ 0x1d, 0x40 },
{ 0x1e, 0x02 },
{ 0x1f, 0xc9 },
/* output state selection */
{ 0x15, 0x00 },
{ 0x14, 0xef },
/* switch MUX to PLL1 output */
{ 0x14, 0x6f },
{ 0x16, 0x06 },
/* set P2DIV divider, P3DIV and input crystal */
{ 0x17, 0x06 },
{ 0x01, 0x00 },
{ 0x05, 0x48 },
{ 0x02, 0x80 },
/* enable and disable PLL */
{ 0x02, 0xbc },
{ 0x03, 0x02 },
{ },
};
static struct cdce_reg cdce_y1_27000[] = {
{ 0x13, 0x00 },
{ 0x18, 0x00 },
{ 0x19, 0x40 },
{ 0x1a, 0x02 },
{ 0x1b, 0x08 },
{ 0x1c, 0x00 },
{ 0x1d, 0x40 },
{ 0x1e, 0x02 },
{ 0x1f, 0x08 },
{ 0x15, 0x02 },
{ 0x14, 0xed },
{ 0x16, 0x01 },
{ 0x17, 0x01 },
{ 0x01, 0x00 },
{ 0x05, 0x50 },
{ 0x02, 0xb4 },
{ 0x03, 0x01 },
{ },
};
static struct cdce_freq cdce_y1_freqs[] = {
CDCE_FREQ_TABLE_ENTRY(1, 148500),
CDCE_FREQ_TABLE_ENTRY(1, 74250),
CDCE_FREQ_TABLE_ENTRY(1, 27000),
};
static struct cdce_reg cdce_y5_13500[] = {
{ 0x27, 0x08 },
{ 0x28, 0x00 },
{ 0x29, 0x40 },
{ 0x2a, 0x02 },
{ 0x2b, 0x08 },
{ 0x24, 0x6f },
{ },
};
static struct cdce_reg cdce_y5_16875[] = {
{ 0x27, 0x08 },
{ 0x28, 0x9f },
{ 0x29, 0xb0 },
{ 0x2a, 0x02 },
{ 0x2b, 0x89 },
{ 0x24, 0x6f },
{ },
};
static struct cdce_reg cdce_y5_27000[] = {
{ 0x27, 0x04 },
{ 0x28, 0x00 },
{ 0x29, 0x40 },
{ 0x2a, 0x02 },
{ 0x2b, 0x08 },
{ 0x24, 0x6f },
{ },
};
static struct cdce_reg cdce_y5_54000[] = {
{ 0x27, 0x04 },
{ 0x28, 0xff },
{ 0x29, 0x80 },
{ 0x2a, 0x02 },
{ 0x2b, 0x07 },
{ 0x24, 0x6f },
{ },
};
static struct cdce_reg cdce_y5_81000[] = {
{ 0x27, 0x02 },
{ 0x28, 0xbf },
{ 0x29, 0xa0 },
{ 0x2a, 0x03 },
{ 0x2b, 0x0a },
{ 0x24, 0x6f },
{ },
};
static struct cdce_freq cdce_y5_freqs[] = {
CDCE_FREQ_TABLE_ENTRY(5, 13500),
CDCE_FREQ_TABLE_ENTRY(5, 16875),
CDCE_FREQ_TABLE_ENTRY(5, 27000),
CDCE_FREQ_TABLE_ENTRY(5, 54000),
CDCE_FREQ_TABLE_ENTRY(5, 81000),
};
static struct cdce_output output_list[] = {
[1] = { cdce_y1_freqs, ARRAY_SIZE(cdce_y1_freqs) },
[5] = { cdce_y5_freqs, ARRAY_SIZE(cdce_y5_freqs) },
};
int cdce_set_rate(struct clk *clk, unsigned long rate)
{
int i, ret = 0;
struct cdce_freq *freq_table = output_list[clk->lpsc].freq_table;
struct cdce_reg *regs = NULL;
if (!cdce_i2c_client)
return -ENODEV;
if (!freq_table)
return -EINVAL;
for (i = 0; i < output_list[clk->lpsc].size; i++) {
if (freq_table[i].frequency == rate / 1000) {
regs = freq_table[i].reglist;
break;
}
}
if (!regs)
return -EINVAL;
mutex_lock(&cdce_mutex);
for (i = 0; regs[i].addr; i++) {
ret = i2c_smbus_write_byte_data(cdce_i2c_client,
regs[i].addr | 0x80, regs[i].val);
if (ret)
break;
}
mutex_unlock(&cdce_mutex);
if (!ret)
clk->rate = rate;
return ret;
}
static int cdce_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
cdce_i2c_client = client;
return 0;
}
static int __devexit cdce_remove(struct i2c_client *client)
{
cdce_i2c_client = NULL;
return 0;
}
static const struct i2c_device_id cdce_id[] = {
{"cdce949", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, cdce_id);
static struct i2c_driver cdce_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "cdce949",
},
.probe = cdce_probe,
.remove = __devexit_p(cdce_remove),
.id_table = cdce_id,
};
static int __init cdce_init(void)
{
return i2c_add_driver(&cdce_driver);
}
subsys_initcall(cdce_init);
static void __exit cdce_exit(void)
{
i2c_del_driver(&cdce_driver);
}
module_exit(cdce_exit);
MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("CDCE949 clock synthesizer driver");
MODULE_LICENSE("GPL v2");

View File

@ -49,7 +49,8 @@ static void __clk_disable(struct clk *clk)
{
if (WARN_ON(clk->usecount == 0))
return;
if (--clk->usecount == 0 && !(clk->flags & CLK_PLL))
if (--clk->usecount == 0 && !(clk->flags & CLK_PLL) &&
(clk->flags & CLK_PSC))
davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0);
if (clk->parent)
__clk_disable(clk->parent);
@ -124,9 +125,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (clk == NULL || IS_ERR(clk))
return ret;
spin_lock_irqsave(&clockfw_lock, flags);
if (clk->set_rate)
ret = clk->set_rate(clk, rate);
spin_lock_irqsave(&clockfw_lock, flags);
if (ret == 0) {
if (clk->recalc)
clk->rate = clk->recalc(clk);
@ -363,6 +365,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
{
u32 ctrl;
unsigned int locktime;
unsigned long flags;
if (pll->base == NULL)
return -EINVAL;
@ -376,25 +379,23 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
locktime = ((2000 * prediv) / 100);
prediv = (prediv - 1) | PLLDIV_EN;
} else {
locktime = 20;
locktime = PLL_LOCK_TIME;
}
if (postdiv)
postdiv = (postdiv - 1) | PLLDIV_EN;
if (mult)
mult = mult - 1;
/* Protect against simultaneous calls to PLL setting seqeunce */
spin_lock_irqsave(&clockfw_lock, flags);
ctrl = __raw_readl(pll->base + PLLCTL);
/* Switch the PLL to bypass mode */
ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
__raw_writel(ctrl, pll->base + PLLCTL);
/*
* Wait for 4 OSCIN/CLKIN cycles to ensure that the PLLC has switched
* to bypass mode. Delay of 1us ensures we are good for all > 4MHz
* OSCIN/CLKIN inputs. Typically the input is ~25MHz.
*/
udelay(1);
udelay(PLL_BYPASS_TIME);
/* Reset and enable PLL */
ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS);
@ -408,11 +409,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
if (pll->flags & PLL_HAS_POSTDIV)
__raw_writel(postdiv, pll->base + POSTDIV);
/*
* Wait for PLL to reset properly, OMAP-L138 datasheet says
* 'min' time = 125ns
*/
udelay(1);
udelay(PLL_RESET_TIME);
/* Bring PLL out of reset */
ctrl |= PLLCTL_PLLRST;
@ -424,17 +421,20 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
ctrl |= PLLCTL_PLLEN;
__raw_writel(ctrl, pll->base + PLLCTL);
spin_unlock_irqrestore(&clockfw_lock, flags);
return 0;
}
EXPORT_SYMBOL(davinci_set_pllrate);
int __init davinci_clk_init(struct davinci_clk *clocks)
int __init davinci_clk_init(struct clk_lookup *clocks)
{
struct davinci_clk *c;
struct clk_lookup *c;
struct clk *clk;
size_t num_clocks = 0;
for (c = clocks; c->lk.clk; c++) {
clk = c->lk.clk;
for (c = clocks; c->clk; c++) {
clk = c->clk;
if (!clk->recalc) {
@ -457,36 +457,24 @@ int __init davinci_clk_init(struct davinci_clk *clocks)
if (clk->lpsc)
clk->flags |= CLK_PSC;
clkdev_add(&c->lk);
clk_register(clk);
num_clocks++;
/* Turn on clocks that Linux doesn't otherwise manage */
if (clk->flags & ALWAYS_ENABLED)
clk_enable(clk);
}
clkdev_add_table(clocks, num_clocks);
return 0;
}
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>
static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
{
return *pos < 1 ? (void *)1 : NULL;
}
static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
{
++*pos;
return NULL;
}
static void davinci_ck_stop(struct seq_file *m, void *v)
{
}
#define CLKNAME_MAX 10 /* longest clock name */
#define NEST_DELTA 2
#define NEST_MAX 4
@ -525,41 +513,38 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
static int davinci_ck_show(struct seq_file *m, void *v)
{
/* Show clock tree; we know the main oscillator is first.
* We trust nonzero usecounts equate to PSC enables...
struct clk *clk;
/*
* Show clock tree; We trust nonzero usecounts equate to PSC enables...
*/
mutex_lock(&clocks_mutex);
if (!list_empty(&clocks))
dump_clock(m, 0, list_first_entry(&clocks, struct clk, node));
list_for_each_entry(clk, &clocks, node)
if (!clk->parent)
dump_clock(m, 0, clk);
mutex_unlock(&clocks_mutex);
return 0;
}
static const struct seq_operations davinci_ck_op = {
.start = davinci_ck_start,
.next = davinci_ck_next,
.stop = davinci_ck_stop,
.show = davinci_ck_show
};
static int davinci_ck_open(struct inode *inode, struct file *file)
{
return seq_open(file, &davinci_ck_op);
return single_open(file, davinci_ck_show, NULL);
}
static const struct file_operations proc_davinci_ck_operations = {
static const struct file_operations davinci_ck_operations = {
.open = davinci_ck_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
.release = single_release,
};
static int __init davinci_ck_proc_init(void)
static int __init davinci_clk_debugfs_init(void)
{
proc_create("davinci_clocks", 0, NULL, &proc_davinci_ck_operations);
debugfs_create_file("davinci_clocks", S_IFREG | S_IRUGO, NULL, NULL,
&davinci_ck_operations);
return 0;
}
__initcall(davinci_ck_proc_init);
#endif /* CONFIG_DEBUG_PROC_FS */
device_initcall(davinci_clk_debugfs_init);
#endif /* CONFIG_DEBUG_FS */

View File

@ -12,9 +12,6 @@
#ifndef __ARCH_ARM_DAVINCI_CLOCK_H
#define __ARCH_ARM_DAVINCI_CLOCK_H
#include <linux/list.h>
#include <asm/clkdev.h>
#define DAVINCI_PLL1_BASE 0x01c40800
#define DAVINCI_PLL2_BASE 0x01c40c00
#define MAX_PLL 2
@ -53,6 +50,26 @@
#define PLLDIV_EN BIT(15)
#define PLLDIV_RATIO_MASK 0x1f
/*
* OMAP-L138 system reference guide recommends a wait for 4 OSCIN/CLKIN
* cycles to ensure that the PLLC has switched to bypass mode. Delay of 1us
* ensures we are good for all > 4MHz OSCIN/CLKIN inputs. Typically the input
* is ~25MHz. Units are micro seconds.
*/
#define PLL_BYPASS_TIME 1
/* From OMAP-L138 datasheet table 6-4. Units are micro seconds */
#define PLL_RESET_TIME 1
/*
* From OMAP-L138 datasheet table 6-4; assuming prediv = 1, sqrt(pllm) = 4
* Units are micro seconds.
*/
#define PLL_LOCK_TIME 20
#ifndef __ASSEMBLER__
#include <linux/list.h>
#include <asm/clkdev.h>
struct pll_data {
u32 phys_base;
void __iomem *base;
@ -89,23 +106,19 @@ struct clk {
#define CLK_PLL BIT(4) /* PLL-derived clock */
#define PRE_PLL BIT(5) /* source is before PLL mult/div */
struct davinci_clk {
struct clk_lookup lk;
};
#define CLK(dev, con, ck) \
{ \
.dev_id = dev, \
.con_id = con, \
.clk = ck, \
} \
#define CLK(dev, con, ck) \
{ \
.lk = { \
.dev_id = dev, \
.con_id = con, \
.clk = ck, \
}, \
}
int davinci_clk_init(struct davinci_clk *clocks);
int davinci_clk_init(struct clk_lookup *clocks);
int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
unsigned int mult, unsigned int postdiv);
extern struct platform_device davinci_wdt_device;
#endif
#endif

View File

@ -11,13 +11,13 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/etherdevice.h>
#include <linux/davinci_emac.h>
#include <asm/tlb.h>
#include <asm/mach/map.h>
#include <mach/common.h>
#include <mach/cputype.h>
#include <mach/emac.h>
#include "clock.h"

View File

@ -19,6 +19,7 @@
#include <asm/proc-fns.h>
#include <mach/cpuidle.h>
#include <mach/memory.h>
#define DAVINCI_CPUIDLE_MAX_STATES 2
@ -39,10 +40,6 @@ static struct cpuidle_driver davinci_idle_driver = {
static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device);
static void __iomem *ddr2_reg_base;
#define DDR2_SDRCR_OFFSET 0xc
#define DDR2_SRPD_BIT BIT(23)
#define DDR2_LPMODEN_BIT BIT(31)
static void davinci_save_ddr_power(int enter, bool pdown)
{
u32 val;
@ -109,8 +106,6 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
int ret;
struct cpuidle_device *device;
struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
struct resource *ddr2_regs;
resource_size_t len;
device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
@ -119,28 +114,12 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
return -ENOENT;
}
ddr2_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!ddr2_regs) {
dev_err(&pdev->dev, "cannot get DDR2 controller register base");
return -ENODEV;
}
len = resource_size(ddr2_regs);
ddr2_regs = request_mem_region(ddr2_regs->start, len, ddr2_regs->name);
if (!ddr2_regs)
return -EBUSY;
ddr2_reg_base = ioremap(ddr2_regs->start, len);
if (!ddr2_reg_base) {
ret = -ENOMEM;
goto ioremap_fail;
}
ddr2_reg_base = pdata->ddr2_ctlr_base;
ret = cpuidle_register_driver(&davinci_idle_driver);
if (ret) {
dev_err(&pdev->dev, "failed to register driver\n");
goto driver_register_fail;
return ret;
}
/* Wait for interrupt state */
@ -167,18 +146,11 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
ret = cpuidle_register_device(device);
if (ret) {
dev_err(&pdev->dev, "failed to register device\n");
goto device_register_fail;
cpuidle_unregister_driver(&davinci_idle_driver);
return ret;
}
return 0;
device_register_fail:
cpuidle_unregister_driver(&davinci_idle_driver);
driver_register_fail:
iounmap(ddr2_reg_base);
ioremap_fail:
release_mem_region(ddr2_regs->start, len);
return ret;
}
static struct platform_driver davinci_cpuidle_driver = {

View File

@ -371,7 +371,7 @@ static struct clk rmii_clk = {
.parent = &pll0_sysclk7,
};
static struct davinci_clk da830_clks[] = {
static struct clk_lookup da830_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "pll0", &pll0_clk),
CLK(NULL, "pll0_aux", &pll0_aux_clk),
@ -1208,13 +1208,13 @@ static struct davinci_soc_info davinci_soc_info_da830 = {
void __init da830_init(void)
{
da8xx_syscfg_base = ioremap(DA8XX_SYSCFG_BASE, SZ_4K);
if (WARN(!da8xx_syscfg_base, "Unable to map syscfg module"))
da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module"))
return;
davinci_soc_info_da830.jtag_id_base =
DA8XX_SYSCFG_VIRT(DA8XX_JTAG_ID_REG);
davinci_soc_info_da830.pinmux_base = DA8XX_SYSCFG_VIRT(0x120);
DA8XX_SYSCFG0_VIRT(DA8XX_JTAG_ID_REG);
davinci_soc_info_da830.pinmux_base = DA8XX_SYSCFG0_VIRT(0x120);
davinci_common_init(&davinci_soc_info_da830);
}

View File

@ -26,6 +26,7 @@
#include <mach/time.h>
#include <mach/da8xx.h>
#include <mach/cpufreq.h>
#include <mach/pm.h>
#include "clock.h"
#include "mux.h"
@ -40,6 +41,7 @@
#define DA850_REF_FREQ 24000000
#define CFGCHIP3_ASYNC3_CLKSRC BIT(4)
#define CFGCHIP3_PLL1_MASTER_LOCK BIT(5)
#define CFGCHIP0_PLL_MASTER_LOCK BIT(4)
static int da850_set_armrate(struct clk *clk, unsigned long rate);
@ -333,7 +335,7 @@ static struct clk aemif_clk = {
.flags = ALWAYS_ENABLED,
};
static struct davinci_clk da850_clks[] = {
static struct clk_lookup da850_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "pll0", &pll0_clk),
CLK(NULL, "pll0_aux", &pll0_aux_clk),
@ -535,6 +537,7 @@ static const struct mux_config da850_pins[] = {
MUX_CFG(DA850, GPIO2_15, 5, 0, 15, 8, false)
MUX_CFG(DA850, GPIO4_0, 10, 28, 15, 8, false)
MUX_CFG(DA850, GPIO4_1, 10, 24, 15, 8, false)
MUX_CFG(DA850, RTC_ALARM, 0, 28, 15, 2, false)
#endif
};
@ -770,6 +773,12 @@ static struct map_desc da850_io_desc[] = {
.length = DA8XX_CP_INTC_SIZE,
.type = MT_DEVICE
},
{
.virtual = SRAM_VIRT,
.pfn = __phys_to_pfn(DA8XX_ARM_RAM_BASE),
.length = SZ_8K,
.type = MT_DEVICE
},
};
static void __iomem *da850_psc_bases[] = {
@ -825,12 +834,12 @@ static struct davinci_timer_info da850_timer_info = {
static void da850_set_async3_src(int pllnum)
{
struct clk *clk, *newparent = pllnum ? &pll1_sysclk2 : &pll0_sysclk2;
struct davinci_clk *c;
struct clk_lookup *c;
unsigned int v;
int ret;
for (c = da850_clks; c->lk.clk; c++) {
clk = c->lk.clk;
for (c = da850_clks; c->clk; c++) {
clk = c->clk;
if (clk->flags & DA850_CLK_ASYNC3) {
ret = clk_set_parent(clk, newparent);
WARN(ret, "DA850: unable to re-parent clock %s",
@ -838,12 +847,12 @@ static void da850_set_async3_src(int pllnum)
}
}
v = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG));
v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
if (pllnum)
v |= CFGCHIP3_ASYNC3_CLKSRC;
else
v &= ~CFGCHIP3_ASYNC3_CLKSRC;
__raw_writel(v, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG));
__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
}
#ifdef CONFIG_CPU_FREQ
@ -987,7 +996,6 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)
unsigned int prediv, mult, postdiv;
struct da850_opp *opp;
struct pll_data *pll = clk->pll_data;
unsigned int v;
int ret;
opp = (struct da850_opp *) da850_freq_table[index].index;
@ -995,11 +1003,6 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)
mult = opp->mult;
postdiv = opp->postdiv;
/* Unlock writing to PLL registers */
v = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP0_REG));
v &= ~CFGCHIP0_PLL_MASTER_LOCK;
__raw_writel(v, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP0_REG));
ret = davinci_set_pllrate(pll, prediv, mult, postdiv);
if (WARN_ON(ret))
return ret;
@ -1028,6 +1031,43 @@ static int da850_round_armrate(struct clk *clk, unsigned long rate)
}
#endif
int da850_register_pm(struct platform_device *pdev)
{
int ret;
struct davinci_pm_config *pdata = pdev->dev.platform_data;
ret = davinci_cfg_reg(DA850_RTC_ALARM);
if (ret)
return ret;
pdata->ddr2_ctlr_base = da8xx_get_mem_ctlr();
pdata->deepsleep_reg = DA8XX_SYSCFG1_VIRT(DA8XX_DEEPSLEEP_REG);
pdata->ddrpsc_num = DA8XX_LPSC1_EMIF3C;
pdata->cpupll_reg_base = ioremap(DA8XX_PLL0_BASE, SZ_4K);
if (!pdata->cpupll_reg_base)
return -ENOMEM;
pdata->ddrpll_reg_base = ioremap(DA8XX_PLL1_BASE, SZ_4K);
if (!pdata->ddrpll_reg_base) {
ret = -ENOMEM;
goto no_ddrpll_mem;
}
pdata->ddrpsc_reg_base = ioremap(DA8XX_PSC1_BASE, SZ_4K);
if (!pdata->ddrpsc_reg_base) {
ret = -ENOMEM;
goto no_ddrpsc_mem;
}
return platform_device_register(pdev);
no_ddrpsc_mem:
iounmap(pdata->ddrpll_reg_base);
no_ddrpll_mem:
iounmap(pdata->cpupll_reg_base);
return ret;
}
static struct davinci_soc_info davinci_soc_info_da850 = {
.io_desc = da850_io_desc,
@ -1049,17 +1089,25 @@ static struct davinci_soc_info davinci_soc_info_da850 = {
.gpio_irq = IRQ_DA8XX_GPIO0,
.serial_dev = &da8xx_serial_device,
.emac_pdata = &da8xx_emac_pdata,
.sram_dma = DA8XX_ARM_RAM_BASE,
.sram_len = SZ_8K,
};
void __init da850_init(void)
{
da8xx_syscfg_base = ioremap(DA8XX_SYSCFG_BASE, SZ_4K);
if (WARN(!da8xx_syscfg_base, "Unable to map syscfg module"))
unsigned int v;
da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module"))
return;
da8xx_syscfg1_base = ioremap(DA8XX_SYSCFG1_BASE, SZ_4K);
if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module"))
return;
davinci_soc_info_da850.jtag_id_base =
DA8XX_SYSCFG_VIRT(DA8XX_JTAG_ID_REG);
davinci_soc_info_da850.pinmux_base = DA8XX_SYSCFG_VIRT(0x120);
DA8XX_SYSCFG0_VIRT(DA8XX_JTAG_ID_REG);
davinci_soc_info_da850.pinmux_base = DA8XX_SYSCFG0_VIRT(0x120);
davinci_common_init(&davinci_soc_info_da850);
@ -1071,4 +1119,14 @@ void __init da850_init(void)
* be any noticible change even in non-DVFS use cases.
*/
da850_set_async3_src(1);
/* Unlock writing to PLL0 registers */
v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
v &= ~CFGCHIP0_PLL_MASTER_LOCK;
__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
/* Unlock writing to PLL1 registers */
v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
v &= ~CFGCHIP3_PLL1_MASTER_LOCK;
__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
}

View File

@ -24,8 +24,10 @@
#include "clock.h"
#define DA8XX_TPCC_BASE 0x01c00000
#define DA850_TPCC1_BASE 0x01e30000
#define DA8XX_TPTC0_BASE 0x01c08000
#define DA8XX_TPTC1_BASE 0x01c08400
#define DA850_TPTC2_BASE 0x01e38000
#define DA8XX_WDOG_BASE 0x01c21000 /* DA8XX_TIMER64P1_BASE */
#define DA8XX_I2C0_BASE 0x01c22000
#define DA8XX_RTC_BASE 0x01C23000
@ -42,7 +44,8 @@
#define DA8XX_MDIO_REG_OFFSET 0x4000
#define DA8XX_EMAC_CTRL_RAM_SIZE SZ_8K
void __iomem *da8xx_syscfg_base;
void __iomem *da8xx_syscfg0_base;
void __iomem *da8xx_syscfg1_base;
static struct plat_serial8250_port da8xx_serial_pdata[] = {
{
@ -82,11 +85,6 @@ struct platform_device da8xx_serial_device = {
},
};
static const s8 da8xx_dma_chan_no_event[] = {
20, 21,
-1
};
static const s8 da8xx_queue_tc_mapping[][2] = {
/* {event queue no, TC no} */
{0, 0},
@ -101,20 +99,52 @@ static const s8 da8xx_queue_priority_mapping[][2] = {
{-1, -1}
};
static struct edma_soc_info da8xx_edma_info[] = {
static const s8 da850_queue_tc_mapping[][2] = {
/* {event queue no, TC no} */
{0, 0},
{-1, -1}
};
static const s8 da850_queue_priority_mapping[][2] = {
/* {event queue no, Priority} */
{0, 3},
{-1, -1}
};
static struct edma_soc_info da830_edma_info[] = {
{
.n_channel = 32,
.n_region = 4,
.n_slot = 128,
.n_tc = 2,
.n_cc = 1,
.noevent = da8xx_dma_chan_no_event,
.queue_tc_mapping = da8xx_queue_tc_mapping,
.queue_priority_mapping = da8xx_queue_priority_mapping,
},
};
static struct resource da8xx_edma_resources[] = {
static struct edma_soc_info da850_edma_info[] = {
{
.n_channel = 32,
.n_region = 4,
.n_slot = 128,
.n_tc = 2,
.n_cc = 1,
.queue_tc_mapping = da8xx_queue_tc_mapping,
.queue_priority_mapping = da8xx_queue_priority_mapping,
},
{
.n_channel = 32,
.n_region = 4,
.n_slot = 128,
.n_tc = 1,
.n_cc = 1,
.queue_tc_mapping = da850_queue_tc_mapping,
.queue_priority_mapping = da850_queue_priority_mapping,
},
};
static struct resource da830_edma_resources[] = {
{
.name = "edma_cc0",
.start = DA8XX_TPCC_BASE,
@ -145,19 +175,91 @@ static struct resource da8xx_edma_resources[] = {
},
};
static struct platform_device da8xx_edma_device = {
static struct resource da850_edma_resources[] = {
{
.name = "edma_cc0",
.start = DA8XX_TPCC_BASE,
.end = DA8XX_TPCC_BASE + SZ_32K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "edma_tc0",
.start = DA8XX_TPTC0_BASE,
.end = DA8XX_TPTC0_BASE + SZ_1K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "edma_tc1",
.start = DA8XX_TPTC1_BASE,
.end = DA8XX_TPTC1_BASE + SZ_1K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "edma_cc1",
.start = DA850_TPCC1_BASE,
.end = DA850_TPCC1_BASE + SZ_32K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "edma_tc2",
.start = DA850_TPTC2_BASE,
.end = DA850_TPTC2_BASE + SZ_1K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "edma0",
.start = IRQ_DA8XX_CCINT0,
.flags = IORESOURCE_IRQ,
},
{
.name = "edma0_err",
.start = IRQ_DA8XX_CCERRINT,
.flags = IORESOURCE_IRQ,
},
{
.name = "edma1",
.start = IRQ_DA850_CCINT1,
.flags = IORESOURCE_IRQ,
},
{
.name = "edma1_err",
.start = IRQ_DA850_CCERRINT1,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device da830_edma_device = {
.name = "edma",
.id = -1,
.dev = {
.platform_data = da8xx_edma_info,
.platform_data = da830_edma_info,
},
.num_resources = ARRAY_SIZE(da8xx_edma_resources),
.resource = da8xx_edma_resources,
.num_resources = ARRAY_SIZE(da830_edma_resources),
.resource = da830_edma_resources,
};
static struct platform_device da850_edma_device = {
.name = "edma",
.id = -1,
.dev = {
.platform_data = da850_edma_info,
},
.num_resources = ARRAY_SIZE(da850_edma_resources),
.resource = da850_edma_resources,
};
int __init da8xx_register_edma(void)
{
return platform_device_register(&da8xx_edma_device);
struct platform_device *pdev;
if (cpu_is_davinci_da830())
pdev = &da830_edma_device;
else if (cpu_is_davinci_da850())
pdev = &da850_edma_device;
else
return -ENODEV;
return platform_device_register(pdev);
}
static struct resource da8xx_i2c_resources0[] = {
@ -495,6 +597,19 @@ int da8xx_register_rtc(void)
return ret;
}
static void __iomem *da8xx_ddr2_ctlr_base;
void __iomem * __init da8xx_get_mem_ctlr(void)
{
if (da8xx_ddr2_ctlr_base)
return da8xx_ddr2_ctlr_base;
da8xx_ddr2_ctlr_base = ioremap(DA8XX_DDR2_CTL_BASE, SZ_32K);
if (!da8xx_ddr2_ctlr_base)
pr_warning("%s: Unable to map DDR2 controller", __func__);
return da8xx_ddr2_ctlr_base;
}
static struct resource da8xx_cpuidle_resources[] = {
{
.start = DA8XX_DDR2_CTL_BASE,
@ -520,6 +635,7 @@ static struct platform_device da8xx_cpuidle_device = {
int __init da8xx_register_cpuidle(void)
{
da8xx_cpuidle_pdata.ddr2_ctlr_base = da8xx_get_mem_ctlr();
return platform_device_register(&da8xx_cpuidle_device);
}

View File

@ -29,6 +29,7 @@
#include <mach/serial.h>
#include <mach/common.h>
#include <mach/asp.h>
#include <mach/spi.h>
#include "clock.h"
#include "mux.h"
@ -334,7 +335,7 @@ static struct clk usb_clk = {
.lpsc = DAVINCI_LPSC_USB,
};
static struct davinci_clk dm355_clks[] = {
static struct clk_lookup dm355_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "pll1", &pll1_clk),
CLK(NULL, "pll1_sysclk1", &pll1_sysclk1),
@ -362,9 +363,9 @@ static struct davinci_clk dm355_clks[] = {
CLK("davinci-asp.1", NULL, &asp1_clk),
CLK("davinci_mmc.0", NULL, &mmcsd0_clk),
CLK("davinci_mmc.1", NULL, &mmcsd1_clk),
CLK(NULL, "spi0", &spi0_clk),
CLK(NULL, "spi1", &spi1_clk),
CLK(NULL, "spi2", &spi2_clk),
CLK("spi_davinci.0", NULL, &spi0_clk),
CLK("spi_davinci.1", NULL, &spi1_clk),
CLK("spi_davinci.2", NULL, &spi2_clk),
CLK(NULL, "gpio", &gpio_clk),
CLK(NULL, "aemif", &aemif_clk),
CLK(NULL, "pwm0", &pwm0_clk),
@ -391,24 +392,40 @@ static struct resource dm355_spi0_resources[] = {
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_DM355_SPINT0_1,
.start = IRQ_DM355_SPINT0_0,
.flags = IORESOURCE_IRQ,
},
/* Not yet used, so not included:
* IORESOURCE_IRQ:
* - IRQ_DM355_SPINT0_0
* IORESOURCE_DMA:
* - DAVINCI_DMA_SPI_SPIX
* - DAVINCI_DMA_SPI_SPIR
*/
{
.start = 17,
.flags = IORESOURCE_DMA,
},
{
.start = 16,
.flags = IORESOURCE_DMA,
},
{
.start = EVENTQ_1,
.flags = IORESOURCE_DMA,
},
};
static struct davinci_spi_platform_data dm355_spi0_pdata = {
.version = SPI_VERSION_1,
.num_chipselect = 2,
.clk_internal = 1,
.cs_hold = 1,
.intr_level = 0,
.poll_mode = 1, /* 0 -> interrupt mode 1-> polling mode */
.c2tdelay = 0,
.t2cdelay = 0,
};
static struct platform_device dm355_spi0_device = {
.name = "spi_davinci",
.id = 0,
.dev = {
.dma_mask = &dm355_spi0_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &dm355_spi0_pdata,
},
.num_resources = ARRAY_SIZE(dm355_spi0_resources),
.resource = dm355_spi0_resources,
@ -563,13 +580,6 @@ static u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
/*----------------------------------------------------------------------*/
static const s8 dma_chan_dm355_no_event[] = {
12, 13, 24, 56, 57,
58, 59, 60, 61, 62,
63,
-1
};
static const s8
queue_tc_mapping[][2] = {
/* {event queue no, TC no} */
@ -593,7 +603,6 @@ static struct edma_soc_info dm355_edma_info[] = {
.n_slot = 128,
.n_tc = 2,
.n_cc = 1,
.noevent = dma_chan_dm355_no_event,
.queue_tc_mapping = queue_tc_mapping,
.queue_priority_mapping = queue_priority_mapping,
},

View File

@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <asm/mach/map.h>
@ -32,6 +33,8 @@
#include <mach/common.h>
#include <mach/asp.h>
#include <mach/keyscan.h>
#include <mach/spi.h>
#include "clock.h"
#include "mux.h"
@ -403,7 +406,7 @@ static struct clk mjcp_clk = {
.lpsc = DM365_LPSC_MJCP,
};
static struct davinci_clk dm365_clks[] = {
static struct clk_lookup dm365_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "pll1", &pll1_clk),
CLK(NULL, "pll1_aux", &pll1_aux_clk),
@ -455,7 +458,7 @@ static struct davinci_clk dm365_clks[] = {
CLK(NULL, "timer3", &timer3_clk),
CLK(NULL, "usb", &usb_clk),
CLK("davinci_emac.1", NULL, &emac_clk),
CLK("voice_codec", NULL, &voicecodec_clk),
CLK("davinci_voicecodec", NULL, &voicecodec_clk),
CLK("davinci-asp.0", NULL, &asp0_clk),
CLK(NULL, "rto", &rto_clk),
CLK(NULL, "mjcp", &mjcp_clk),
@ -606,9 +609,78 @@ INT_CFG(DM365, INT_NSF_DISABLE, 25, 1, 0, false)
EVT_CFG(DM365, EVT2_ASP_TX, 0, 1, 0, false)
EVT_CFG(DM365, EVT3_ASP_RX, 1, 1, 0, false)
EVT_CFG(DM365, EVT2_VC_TX, 0, 1, 1, false)
EVT_CFG(DM365, EVT3_VC_RX, 1, 1, 1, false)
#endif
};
static u64 dm365_spi0_dma_mask = DMA_BIT_MASK(32);
static struct davinci_spi_platform_data dm365_spi0_pdata = {
.version = SPI_VERSION_1,
.num_chipselect = 2,
.clk_internal = 1,
.cs_hold = 1,
.intr_level = 0,
.poll_mode = 1, /* 0 -> interrupt mode 1-> polling mode */
.c2tdelay = 0,
.t2cdelay = 0,
};
static struct resource dm365_spi0_resources[] = {
{
.start = 0x01c66000,
.end = 0x01c667ff,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_DM365_SPIINT0_0,
.flags = IORESOURCE_IRQ,
},
{
.start = 17,
.flags = IORESOURCE_DMA,
},
{
.start = 16,
.flags = IORESOURCE_DMA,
},
{
.start = EVENTQ_3,
.flags = IORESOURCE_DMA,
},
};
static struct platform_device dm365_spi0_device = {
.name = "spi_davinci",
.id = 0,
.dev = {
.dma_mask = &dm365_spi0_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &dm365_spi0_pdata,
},
.num_resources = ARRAY_SIZE(dm365_spi0_resources),
.resource = dm365_spi0_resources,
};
void __init dm365_init_spi0(unsigned chipselect_mask,
struct spi_board_info *info, unsigned len)
{
davinci_cfg_reg(DM365_SPI0_SCLK);
davinci_cfg_reg(DM365_SPI0_SDI);
davinci_cfg_reg(DM365_SPI0_SDO);
/* not all slaves will be wired up */
if (chipselect_mask & BIT(0))
davinci_cfg_reg(DM365_SPI0_SDENA0);
if (chipselect_mask & BIT(1))
davinci_cfg_reg(DM365_SPI0_SDENA1);
spi_register_board_info(info, len);
platform_device_register(&dm365_spi0_device);
}
static struct emac_platform_data dm365_emac_pdata = {
.ctrl_reg_offset = DM365_EMAC_CNTRL_OFFSET,
.ctrl_mod_reg_offset = DM365_EMAC_CNTRL_MOD_OFFSET,
@ -754,7 +826,7 @@ static struct edma_soc_info dm365_edma_info[] = {
.n_cc = 1,
.queue_tc_mapping = dm365_queue_tc_mapping,
.queue_priority_mapping = dm365_queue_priority_mapping,
.default_queue = EVENTQ_2,
.default_queue = EVENTQ_3,
},
};
@ -835,6 +907,31 @@ static struct platform_device dm365_asp_device = {
.resource = dm365_asp_resources,
};
static struct resource dm365_vc_resources[] = {
{
.start = DAVINCI_DM365_VC_BASE,
.end = DAVINCI_DM365_VC_BASE + SZ_1K - 1,
.flags = IORESOURCE_MEM,
},
{
.start = DAVINCI_DMA_VC_TX,
.end = DAVINCI_DMA_VC_TX,
.flags = IORESOURCE_DMA,
},
{
.start = DAVINCI_DMA_VC_RX,
.end = DAVINCI_DMA_VC_RX,
.flags = IORESOURCE_DMA,
},
};
static struct platform_device dm365_vc_device = {
.name = "davinci_voicecodec",
.id = -1,
.num_resources = ARRAY_SIZE(dm365_vc_resources),
.resource = dm365_vc_resources,
};
static struct resource dm365_rtc_resources[] = {
{
.start = DM365_RTC_BASE,
@ -991,6 +1088,14 @@ void __init dm365_init_asp(struct snd_platform_data *pdata)
platform_device_register(&dm365_asp_device);
}
void __init dm365_init_vc(struct snd_platform_data *pdata)
{
davinci_cfg_reg(DM365_EVT2_VC_TX);
davinci_cfg_reg(DM365_EVT3_VC_RX);
dm365_vc_device.dev.platform_data = pdata;
platform_device_register(&dm365_vc_device);
}
void __init dm365_init_ks(struct davinci_ks_platform_data *pdata)
{
dm365_ks_device.dev.platform_data = pdata;

View File

@ -277,7 +277,7 @@ static struct clk timer2_clk = {
.usecount = 1, /* REVISIT: why cant' this be disabled? */
};
struct davinci_clk dm644x_clks[] = {
struct clk_lookup dm644x_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "pll1", &pll1_clk),
CLK(NULL, "pll1_sysclk1", &pll1_sysclk1),
@ -479,15 +479,6 @@ static u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
/*----------------------------------------------------------------------*/
static const s8 dma_chan_dm644x_no_event[] = {
0, 1, 12, 13, 14,
15, 25, 30, 31, 45,
46, 47, 55, 56, 57,
58, 59, 60, 61, 62,
63,
-1
};
static const s8
queue_tc_mapping[][2] = {
/* {event queue no, TC no} */
@ -511,7 +502,6 @@ static struct edma_soc_info dm644x_edma_info[] = {
.n_slot = 128,
.n_tc = 2,
.n_cc = 1,
.noevent = dma_chan_dm644x_no_event,
.queue_tc_mapping = queue_tc_mapping,
.queue_priority_mapping = queue_priority_mapping,
},

View File

@ -42,7 +42,6 @@
/*
* Device specific clocks
*/
#define DM646X_REF_FREQ 27000000
#define DM646X_AUX_FREQ 24000000
static struct pll_data pll1_data = {
@ -57,7 +56,6 @@ static struct pll_data pll2_data = {
static struct clk ref_clk = {
.name = "ref_clk",
.rate = DM646X_REF_FREQ,
};
static struct clk aux_clkin = {
@ -313,7 +311,7 @@ static struct clk vpif1_clk = {
.flags = ALWAYS_ENABLED,
};
struct davinci_clk dm646x_clks[] = {
struct clk_lookup dm646x_clks[] = {
CLK(NULL, "ref", &ref_clk),
CLK(NULL, "aux", &aux_clkin),
CLK(NULL, "pll1", &pll1_clk),
@ -513,14 +511,6 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
/*----------------------------------------------------------------------*/
static const s8 dma_chan_dm646x_no_event[] = {
0, 1, 2, 3, 13,
14, 15, 24, 25, 26,
27, 30, 31, 54, 55,
56,
-1
};
/* Four Transfer Controllers on DM646x */
static const s8
dm646x_queue_tc_mapping[][2] = {
@ -549,7 +539,6 @@ static struct edma_soc_info dm646x_edma_info[] = {
.n_slot = 512,
.n_tc = 4,
.n_cc = 1,
.noevent = dma_chan_dm646x_no_event,
.queue_tc_mapping = dm646x_queue_tc_mapping,
.queue_priority_mapping = dm646x_queue_priority_mapping,
},
@ -925,6 +914,7 @@ void dm646x_setup_vpif(struct vpif_display_config *display_config,
void __init dm646x_init(void)
{
dm646x_board_setup_refclk(&ref_clk);
davinci_common_init(&davinci_soc_info_dm646x);
}

View File

@ -226,11 +226,11 @@ struct edma {
*/
DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
/* The edma_noevent bit for each channel is clear unless
* it doesn't trigger DMA events on this platform. It uses a
* bit of SOC-specific initialization code.
/* The edma_unused bit for each channel is clear unless
* it is not being used on this platform. It uses a bit
* of SOC-specific initialization code.
*/
DECLARE_BITMAP(edma_noevent, EDMA_MAX_DMACH);
DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH);
unsigned irq_res_start;
unsigned irq_res_end;
@ -243,6 +243,7 @@ struct edma {
};
static struct edma *edma_info[EDMA_MAX_CC];
static int arch_num_cc;
/* dummy param set used to (re)initialize parameter RAM slots */
static const struct edmacc_param dummy_paramset = {
@ -555,8 +556,27 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id,
return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1);
}
static int prepare_unused_channel_list(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
int i, ctlr;
for (i = 0; i < pdev->num_resources; i++) {
if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
(int)pdev->resource[i].start >= 0) {
ctlr = EDMA_CTLR(pdev->resource[i].start);
clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
edma_info[ctlr]->edma_unused);
}
}
return 0;
}
/*-----------------------------------------------------------------------*/
static bool unused_chan_list_done;
/* Resource alloc/free: dma channels, parameter RAM slots */
/**
@ -594,7 +614,22 @@ int edma_alloc_channel(int channel,
void *data,
enum dma_event_q eventq_no)
{
unsigned i, done, ctlr = 0;
unsigned i, done = 0, ctlr = 0;
int ret = 0;
if (!unused_chan_list_done) {
/*
* Scan all the platform devices to find out the EDMA channels
* used and clear them in the unused list, making the rest
* available for ARM usage.
*/
ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
prepare_unused_channel_list);
if (ret < 0)
return ret;
unused_chan_list_done = true;
}
if (channel >= 0) {
ctlr = EDMA_CTLR(channel);
@ -602,15 +637,15 @@ int edma_alloc_channel(int channel,
}
if (channel < 0) {
for (i = 0; i < EDMA_MAX_CC; i++) {
for (i = 0; i < arch_num_cc; i++) {
channel = 0;
for (;;) {
channel = find_next_bit(edma_info[i]->
edma_noevent,
edma_unused,
edma_info[i]->num_channels,
channel);
if (channel == edma_info[i]->num_channels)
return -ENOMEM;
break;
if (!test_and_set_bit(channel,
edma_info[i]->edma_inuse)) {
done = 1;
@ -622,6 +657,8 @@ int edma_alloc_channel(int channel,
if (done)
break;
}
if (!done)
return -ENOMEM;
} else if (channel >= edma_info[ctlr]->num_channels) {
return -EINVAL;
} else if (test_and_set_bit(channel, edma_info[ctlr]->edma_inuse)) {
@ -642,7 +679,7 @@ int edma_alloc_channel(int channel,
map_dmach_queue(ctlr, channel, eventq_no);
return channel;
return EDMA_CTLR_CHAN(ctlr, channel);
}
EXPORT_SYMBOL(edma_alloc_channel);
@ -1219,7 +1256,7 @@ int edma_start(unsigned channel)
unsigned int mask = (1 << (channel & 0x1f));
/* EDMA channels without event association */
if (test_bit(channel, edma_info[ctlr]->edma_noevent)) {
if (test_bit(channel, edma_info[ctlr]->edma_unused)) {
pr_debug("EDMA: ESR%d %08x\n", j,
edma_shadow0_read_array(ctlr, SH_ESR, j));
edma_shadow0_write_array(ctlr, SH_ESR, j, mask);
@ -1344,7 +1381,6 @@ static int __init edma_probe(struct platform_device *pdev)
const s8 (*queue_tc_mapping)[2];
int i, j, found = 0;
int status = -1;
const s8 *noevent;
int irq[EDMA_MAX_CC] = {0, 0};
int err_irq[EDMA_MAX_CC] = {0, 0};
struct resource *r[EDMA_MAX_CC] = {NULL};
@ -1407,11 +1443,9 @@ static int __init edma_probe(struct platform_device *pdev)
memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
&dummy_paramset, PARM_SIZE);
noevent = info[j].noevent;
if (noevent) {
while (*noevent != -1)
set_bit(*noevent++, edma_info[j]->edma_noevent);
}
/* Mark all channels as unused */
memset(edma_info[j]->edma_unused, 0xff,
sizeof(edma_info[j]->edma_unused));
sprintf(irq_name, "edma%d", j);
irq[j] = platform_get_irq_byname(pdev, irq_name);
@ -1467,6 +1501,7 @@ static int __init edma_probe(struct platform_device *pdev)
edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
edma_write_array(j, EDMA_QRAE, i, 0x0);
}
arch_num_cc++;
}
if (tc_errs_handled) {

View File

@ -0,0 +1,19 @@
/*
* TI CDCE949 off-chip clock synthesizer support
*
* 2009 (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_CDCE949_H
#define _MACH_DAVINCI_CDCE949_H
#include <linux/clk.h>
#include <mach/clock.h>
int cdce_set_rate(struct clk *clk, unsigned long rate);
#endif

View File

@ -43,7 +43,7 @@ struct davinci_soc_info {
void __iomem *jtag_id_base;
struct davinci_id *ids;
unsigned long ids_num;
struct davinci_clk *cpu_clks;
struct clk_lookup *cpu_clks;
void __iomem **psc_bases;
unsigned long psc_bases_num;
void __iomem *pinmux_base;

View File

@ -12,6 +12,7 @@
struct davinci_cpuidle_config {
u32 ddr2_pdown;
void __iomem *ddr2_ctlr_base;
};
#endif

View File

@ -13,15 +13,17 @@
#include <video/da8xx-fb.h>
#include <linux/davinci_emac.h>
#include <mach/serial.h>
#include <mach/edma.h>
#include <mach/i2c.h>
#include <mach/emac.h>
#include <mach/asp.h>
#include <mach/mmc.h>
#include <mach/usb.h>
#include <mach/pm.h>
extern void __iomem *da8xx_syscfg_base;
extern void __iomem *da8xx_syscfg0_base;
extern void __iomem *da8xx_syscfg1_base;
/*
* The cp_intc interrupt controller for the da8xx isn't in the same
@ -34,13 +36,17 @@ extern void __iomem *da8xx_syscfg_base;
#define DA8XX_CP_INTC_SIZE SZ_8K
#define DA8XX_CP_INTC_VIRT (IO_VIRT - DA8XX_CP_INTC_SIZE - SZ_4K)
#define DA8XX_SYSCFG_BASE (IO_PHYS + 0x14000)
#define DA8XX_SYSCFG_VIRT(x) (da8xx_syscfg_base + (x))
#define DA8XX_SYSCFG0_BASE (IO_PHYS + 0x14000)
#define DA8XX_SYSCFG0_VIRT(x) (da8xx_syscfg0_base + (x))
#define DA8XX_JTAG_ID_REG 0x18
#define DA8XX_CFGCHIP0_REG 0x17c
#define DA8XX_CFGCHIP2_REG 0x184
#define DA8XX_CFGCHIP3_REG 0x188
#define DA8XX_SYSCFG1_BASE (IO_PHYS + 0x22C000)
#define DA8XX_SYSCFG1_VIRT(x) (da8xx_syscfg1_base + (x))
#define DA8XX_DEEPSLEEP_REG 0x8
#define DA8XX_PSC0_BASE 0x01c10000
#define DA8XX_PLL0_BASE 0x01c11000
#define DA8XX_TIMER64P0_BASE 0x01c20000
@ -48,11 +54,13 @@ extern void __iomem *da8xx_syscfg_base;
#define DA8XX_GPIO_BASE 0x01e26000
#define DA8XX_PSC1_BASE 0x01e27000
#define DA8XX_LCD_CNTRL_BASE 0x01e13000
#define DA8XX_PLL1_BASE 0x01e1a000
#define DA8XX_MMCSD0_BASE 0x01c40000
#define DA8XX_AEMIF_CS2_BASE 0x60000000
#define DA8XX_AEMIF_CS3_BASE 0x62000000
#define DA8XX_AEMIF_CTL_BASE 0x68000000
#define DA8XX_DDR2_CTL_BASE 0xb0000000
#define DA8XX_ARM_RAM_BASE 0xffff0000
#define PINMUX0 0x00
#define PINMUX1 0x04
@ -90,6 +98,8 @@ void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata);
int da8xx_register_rtc(void);
int da850_register_cpufreq(void);
int da8xx_register_cpuidle(void);
void __iomem * __init da8xx_get_mem_ctlr(void);
int da850_register_pm(struct platform_device *pdev);
extern struct platform_device da8xx_serial_device;
extern struct emac_platform_data da8xx_emac_pdata;

View File

@ -14,8 +14,8 @@
#define __ASM_ARCH_DM665_H
#include <linux/platform_device.h>
#include <linux/davinci_emac.h>
#include <mach/hardware.h>
#include <mach/emac.h>
#include <mach/asp.h>
#include <mach/keyscan.h>
#include <media/davinci/vpfe_capture.h>
@ -32,10 +32,17 @@
#define DM365_RTC_BASE (0x01C69000)
#define DAVINCI_DM365_VC_BASE (0x01D0C000)
#define DAVINCI_DMA_VC_TX 2
#define DAVINCI_DMA_VC_RX 3
void __init dm365_init(void);
void __init dm365_init_asp(struct snd_platform_data *pdata);
void __init dm365_init_vc(struct snd_platform_data *pdata);
void __init dm365_init_ks(struct davinci_ks_platform_data *pdata);
void __init dm365_init_rtc(void);
void dm365_init_spi0(unsigned chipselect_mask,
struct spi_board_info *info, unsigned len);
void dm365_set_vpfe_config(struct vpfe_config *cfg);
#endif /* __ASM_ARCH_DM365_H */

View File

@ -22,8 +22,8 @@
#ifndef __ASM_ARCH_DM644X_H
#define __ASM_ARCH_DM644X_H
#include <linux/davinci_emac.h>
#include <mach/hardware.h>
#include <mach/emac.h>
#include <mach/asp.h>
#include <media/davinci/vpfe_capture.h>

View File

@ -12,10 +12,11 @@
#define __ASM_ARCH_DM646X_H
#include <mach/hardware.h>
#include <mach/emac.h>
#include <mach/asp.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <linux/clk.h>
#include <linux/davinci_emac.h>
#define DM646X_EMAC_BASE (0x01C80000)
#define DM646X_EMAC_CNTRL_OFFSET (0x0000)
@ -30,6 +31,7 @@ void __init dm646x_init(void);
void __init dm646x_init_ide(void);
void __init dm646x_init_mcasp0(struct snd_platform_data *pdata);
void __init dm646x_init_mcasp1(struct snd_platform_data *pdata);
void __init dm646x_board_setup_refclk(struct clk *clk);
void dm646x_video_init(void);

View File

@ -280,8 +280,6 @@ struct edma_soc_info {
unsigned n_cc;
enum dma_event_q default_queue;
/* list of channels with no even trigger; terminated by "-1" */
const s8 *noevent;
const s8 (*queue_tc_mapping)[2];
const s8 (*queue_priority_mapping)[2];
};

View File

@ -16,6 +16,8 @@
struct davinci_i2c_platform_data {
unsigned int bus_freq; /* standard bus frequency (kHz) */
unsigned int bus_delay; /* post-transaction delay (usec) */
unsigned int sda_pin; /* GPIO pin ID to use for SDA */
unsigned int scl_pin; /* GPIO pin ID to use for SCL */
};
/* for board setup code */

View File

@ -31,6 +31,11 @@
#define PHYS_OFFSET DAVINCI_DDR_BASE
#endif
#define DDR2_SDRCR_OFFSET 0xc
#define DDR2_SRPD_BIT BIT(23)
#define DDR2_MCLKSTOPEN_BIT BIT(30)
#define DDR2_LPMODEN_BIT BIT(31)
/*
* Increase size of DMA-consistent memory region
*/

View File

@ -327,6 +327,8 @@ enum davinci_dm365_index {
/* EDMA event muxing */
DM365_EVT2_ASP_TX,
DM365_EVT3_ASP_RX,
DM365_EVT2_VC_TX,
DM365_EVT3_VC_RX,
DM365_EVT26_MMC0_RX,
};
@ -899,6 +901,7 @@ enum davinci_da850_index {
DA850_GPIO2_15,
DA850_GPIO4_0,
DA850_GPIO4_1,
DA850_RTC_ALARM,
};
#ifdef CONFIG_DAVINCI_MUX

View File

@ -0,0 +1,54 @@
/*
* TI DaVinci platform support for power management.
*
* Copyright (C) 2009 Texas Instruments, Inc. 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 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 _MACH_DAVINCI_PM_H
#define _MACH_DAVINCI_PM_H
/*
* Caution: Assembly code in sleep.S makes assumtion on the order
* of the members of this structure.
*/
struct davinci_pm_config {
void __iomem *ddr2_ctlr_base;
void __iomem *ddrpsc_reg_base;
int ddrpsc_num;
void __iomem *ddrpll_reg_base;
void __iomem *deepsleep_reg;
void __iomem *cpupll_reg_base;
/*
* Note on SLEEPCOUNT:
* The SLEEPCOUNT feature is mainly intended for cases in which
* the internal oscillator is used. The internal oscillator is
* fully disabled in deep sleep mode. When you exist deep sleep
* mode, the oscillator will be turned on and will generate very
* small oscillations which will not be detected by the deep sleep
* counter. Eventually those oscillations will grow to an amplitude
* large enough to start incrementing the deep sleep counter.
* In this case recommendation from hardware engineers is that the
* SLEEPCOUNT be set to 4096. This means that 4096 valid clock cycles
* must be detected before the clock is passed to the rest of the
* system.
* In the case that the internal oscillator is not used and the
* clock is generated externally, the SLEEPCOUNT value can be very
* small since the clock input is assumed to be stable before SoC
* is taken out of deepsleep mode. A value of 128 would be more than
* adequate.
*/
int sleepcount;
};
extern unsigned int davinci_cpu_suspend_sz;
extern void davinci_cpu_suspend(struct davinci_pm_config *);
#endif

View File

@ -180,8 +180,23 @@
#define DA8XX_LPSC1_CR_P3_SS 26
#define DA8XX_LPSC1_L3_CBA_RAM 31
/* PSC register offsets */
#define EPCPR 0x070
#define PTCMD 0x120
#define PTSTAT 0x128
#define PDSTAT 0x200
#define PDCTL1 0x304
#define MDSTAT 0x800
#define MDCTL 0xA00
#define MDSTAT_STATE_MASK 0x1f
#ifndef __ASSEMBLER__
extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
unsigned int id, char enable);
#endif
#endif /* __ASM_ARCH_PSC_H */

View File

@ -0,0 +1,44 @@
/*
* Copyright 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.
*/
#ifndef __ARCH_ARM_DAVINCI_SPI_H
#define __ARCH_ARM_DAVINCI_SPI_H
enum {
SPI_VERSION_1, /* For DM355/DM365/DM6467 */
SPI_VERSION_2, /* For DA8xx */
};
struct davinci_spi_platform_data {
u8 version;
u8 num_chipselect;
u8 wdelay;
u8 odd_parity;
u8 parity_enable;
u8 wait_enable;
u8 timer_disable;
u8 clk_internal;
u8 cs_hold;
u8 intr_level;
u8 poll_mode;
u8 use_dma;
u8 c2tdelay;
u8 t2cdelay;
};
#endif /* __ARCH_ARM_DAVINCI_SPI_H */

View File

@ -11,7 +11,12 @@
#ifndef __ASM_ARCH_TIMEX_H
#define __ASM_ARCH_TIMEX_H
/* The source frequency for the timers is the 27MHz clock */
/*
* Alert: Not all timers of the DaVinci family run at a frequency of 27MHz,
* but we should be fine as long as CLOCK_TICK_RATE or LATCH (see include/
* linux/jiffies.h) are not used directly in code. Currently none of the
* code relevant to DaVinci platform depends on these values directly.
*/
#define CLOCK_TICK_RATE 27000000
#endif /* __ASM_ARCH_TIMEX_H__ */

158
arch/arm/mach-davinci/pm.c Normal file
View File

@ -0,0 +1,158 @@
/*
* DaVinci Power Management Routines
*
* Copyright (C) 2009 Texas Instruments, Inc. 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/pm.h>
#include <linux/suspend.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/spinlock.h>
#include <asm/cacheflush.h>
#include <asm/delay.h>
#include <mach/da8xx.h>
#include <mach/sram.h>
#include <mach/pm.h>
#include "clock.h"
#define DEEPSLEEP_SLEEPCOUNT_MASK 0xFFFF
static void (*davinci_sram_suspend) (struct davinci_pm_config *);
static struct davinci_pm_config *pdata;
static void davinci_sram_push(void *dest, void *src, unsigned int size)
{
memcpy(dest, src, size);
flush_icache_range((unsigned long)dest, (unsigned long)(dest + size));
}
static void davinci_pm_suspend(void)
{
unsigned val;
if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
/* Switch CPU PLL to bypass mode */
val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
val &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
udelay(PLL_BYPASS_TIME);
/* Powerdown CPU PLL */
val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
val |= PLLCTL_PLLPWRDN;
__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
}
/* Configure sleep count in deep sleep register */
val = __raw_readl(pdata->deepsleep_reg);
val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
val |= pdata->sleepcount;
__raw_writel(val, pdata->deepsleep_reg);
/* System goes to sleep in this call */
davinci_sram_suspend(pdata);
if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
/* put CPU PLL in reset */
val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
val &= ~PLLCTL_PLLRST;
__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
/* put CPU PLL in power down */
val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
val &= ~PLLCTL_PLLPWRDN;
__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
/* wait for CPU PLL reset */
udelay(PLL_RESET_TIME);
/* bring CPU PLL out of reset */
val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
val |= PLLCTL_PLLRST;
__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
/* Wait for CPU PLL to lock */
udelay(PLL_LOCK_TIME);
/* Remove CPU PLL from bypass mode */
val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
val &= ~PLLCTL_PLLENSRC;
val |= PLLCTL_PLLEN;
__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
}
}
static int davinci_pm_enter(suspend_state_t state)
{
int ret = 0;
switch (state) {
case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
davinci_pm_suspend();
break;
default:
ret = -EINVAL;
}
return ret;
}
static struct platform_suspend_ops davinci_pm_ops = {
.enter = davinci_pm_enter,
.valid = suspend_valid_only_mem,
};
static int __init davinci_pm_probe(struct platform_device *pdev)
{
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "cannot get platform data\n");
return -ENOENT;
}
davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL);
if (!davinci_sram_suspend) {
dev_err(&pdev->dev, "cannot allocate SRAM memory\n");
return -ENOMEM;
}
davinci_sram_push(davinci_sram_suspend, davinci_cpu_suspend,
davinci_cpu_suspend_sz);
suspend_set_ops(&davinci_pm_ops);
return 0;
}
static int __exit davinci_pm_remove(struct platform_device *pdev)
{
sram_free(davinci_sram_suspend, davinci_cpu_suspend_sz);
return 0;
}
static struct platform_driver davinci_pm_driver = {
.driver = {
.name = "pm-davinci",
.owner = THIS_MODULE,
},
.remove = __exit_p(davinci_pm_remove),
};
static int __init davinci_pm_init(void)
{
return platform_driver_probe(&davinci_pm_driver, davinci_pm_probe);
}
late_initcall(davinci_pm_init);

View File

@ -25,17 +25,6 @@
#include <mach/cputype.h>
#include <mach/psc.h>
/* PSC register offsets */
#define EPCPR 0x070
#define PTCMD 0x120
#define PTSTAT 0x128
#define PDSTAT 0x200
#define PDCTL1 0x304
#define MDSTAT 0x800
#define MDCTL 0xA00
#define MDSTAT_STATE_MASK 0x1f
/* Return nonzero iff the domain's clock is active */
int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
{

View File

@ -0,0 +1,224 @@
/*
* (C) Copyright 2009, Texas Instruments, Inc. 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.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/* replicated define because linux/bitops.h cannot be included in assembly */
#define BIT(nr) (1 << (nr))
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <mach/psc.h>
#include <mach/memory.h>
#include "clock.h"
/* Arbitrary, hardware currently does not update PHYRDY correctly */
#define PHYRDY_CYCLES 0x1000
/* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */
#define PLL_BYPASS_CYCLES (PLL_BYPASS_TIME * 25)
#define PLL_RESET_CYCLES (PLL_RESET_TIME * 25)
#define PLL_LOCK_CYCLES (PLL_LOCK_TIME * 25)
#define DEEPSLEEP_SLEEPENABLE_BIT BIT(31)
.text
/*
* Move DaVinci into deep sleep state
*
* Note: This code is copied to internal SRAM by PM code. When the DaVinci
* wakes up it continues execution at the point it went to sleep.
* Register Usage:
* r0: contains virtual base for DDR2 controller
* r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
* r2: contains PSC number for DDR2
* r3: contains virtual base DDR2 PLL controller
* r4: contains virtual address of the DEEPSLEEP register
*/
ENTRY(davinci_cpu_suspend)
stmfd sp!, {r0-r12, lr} @ save registers on stack
ldr ip, CACHE_FLUSH
blx ip
ldmia r0, {r0-r4}
/*
* Switch DDR to self-refresh mode.
*/
/* calculate SDRCR address */
ldr ip, [r0, #DDR2_SDRCR_OFFSET]
bic ip, ip, #DDR2_SRPD_BIT
orr ip, ip, #DDR2_LPMODEN_BIT
str ip, [r0, #DDR2_SDRCR_OFFSET]
ldr ip, [r0, #DDR2_SDRCR_OFFSET]
orr ip, ip, #DDR2_MCLKSTOPEN_BIT
str ip, [r0, #DDR2_SDRCR_OFFSET]
mov ip, #PHYRDY_CYCLES
1: subs ip, ip, #0x1
bne 1b
/* Disable DDR2 LPSC */
mov r7, r0
mov r0, #0x2
bl davinci_ddr_psc_config
mov r0, r7
/* Disable clock to DDR PHY */
ldr ip, [r3, #PLLDIV1]
bic ip, ip, #PLLDIV_EN
str ip, [r3, #PLLDIV1]
/* Put the DDR PLL in bypass and power down */
ldr ip, [r3, #PLLCTL]
bic ip, ip, #PLLCTL_PLLENSRC
bic ip, ip, #PLLCTL_PLLEN
str ip, [r3, #PLLCTL]
/* Wait for PLL to switch to bypass */
mov ip, #PLL_BYPASS_CYCLES
2: subs ip, ip, #0x1
bne 2b
/* Power down the PLL */
ldr ip, [r3, #PLLCTL]
orr ip, ip, #PLLCTL_PLLPWRDN
str ip, [r3, #PLLCTL]
/* Go to deep sleep */
ldr ip, [r4]
orr ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
/* System goes to sleep beyond after this instruction */
str ip, [r4]
/* Wake up from sleep */
/* Clear sleep enable */
ldr ip, [r4]
bic ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
str ip, [r4]
/* initialize the DDR PLL controller */
/* Put PLL in reset */
ldr ip, [r3, #PLLCTL]
bic ip, ip, #PLLCTL_PLLRST
str ip, [r3, #PLLCTL]
/* Clear PLL power down */
ldr ip, [r3, #PLLCTL]
bic ip, ip, #PLLCTL_PLLPWRDN
str ip, [r3, #PLLCTL]
mov ip, #PLL_RESET_CYCLES
3: subs ip, ip, #0x1
bne 3b
/* Bring PLL out of reset */
ldr ip, [r3, #PLLCTL]
orr ip, ip, #PLLCTL_PLLRST
str ip, [r3, #PLLCTL]
/* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
mov ip, #PLL_LOCK_CYCLES
4: subs ip, ip, #0x1
bne 4b
/* Remove PLL from bypass mode */
ldr ip, [r3, #PLLCTL]
bic ip, ip, #PLLCTL_PLLENSRC
orr ip, ip, #PLLCTL_PLLEN
str ip, [r3, #PLLCTL]
/* Start 2x clock to DDR2 */
ldr ip, [r3, #PLLDIV1]
orr ip, ip, #PLLDIV_EN
str ip, [r3, #PLLDIV1]
/* Enable VCLK */
/* Enable DDR2 LPSC */
mov r7, r0
mov r0, #0x3
bl davinci_ddr_psc_config
mov r0, r7
/* clear MCLKSTOPEN */
ldr ip, [r0, #DDR2_SDRCR_OFFSET]
bic ip, ip, #DDR2_MCLKSTOPEN_BIT
str ip, [r0, #DDR2_SDRCR_OFFSET]
ldr ip, [r0, #DDR2_SDRCR_OFFSET]
bic ip, ip, #DDR2_LPMODEN_BIT
str ip, [r0, #DDR2_SDRCR_OFFSET]
/* Restore registers and return */
ldmfd sp!, {r0-r12, pc}
ENDPROC(davinci_cpu_suspend)
/*
* Disables or Enables DDR2 LPSC
* Register Usage:
* r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
* r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
* r2: contains PSC number for DDR2
*/
ENTRY(davinci_ddr_psc_config)
/* Set next state in mdctl for DDR2 */
mov r6, #MDCTL
add r6, r6, r2, lsl #2
ldr ip, [r1, r6]
bic ip, ip, #MDSTAT_STATE_MASK
orr ip, ip, r0
str ip, [r1, r6]
/* Enable the Power Domain Transition Command */
ldr ip, [r1, #PTCMD]
orr ip, ip, #0x1
str ip, [r1, #PTCMD]
/* Check for Transition Complete (PTSTAT) */
ptstat_done:
ldr ip, [r1, #PTSTAT]
and ip, ip, #0x1
cmp ip, #0x0
bne ptstat_done
/* Check for DDR2 clock disable completion; */
mov r6, #MDSTAT
add r6, r6, r2, lsl #2
ddr2clk_stop_done:
ldr ip, [r1, r6]
and ip, ip, #MDSTAT_STATE_MASK
cmp ip, r0
bne ddr2clk_stop_done
mov pc, lr
ENDPROC(davinci_ddr_psc_config)
CACHE_FLUSH:
.word arm926_flush_kern_cache_all
ENTRY(davinci_cpu_suspend_sz)
.word . - davinci_cpu_suspend
ENDPROC(davinci_cpu_suspend_sz)

View File

@ -920,7 +920,7 @@ config NET_NETX
config TI_DAVINCI_EMAC
tristate "TI DaVinci EMAC Support"
depends on ARM && ARCH_DAVINCI
depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
select PHYLIB
help
This driver supports TI's DaVinci Ethernet .

View File

@ -62,12 +62,11 @@
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/davinci_emac.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <mach/emac.h>
static int debug_level;
module_param(debug_level, int, 0);
MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)");
@ -465,6 +464,7 @@ struct emac_priv {
void __iomem *ctrl_base;
void __iomem *emac_ctrl_ram;
u32 ctrl_ram_size;
u32 hw_ram_addr;
struct emac_txch *txch[EMAC_DEF_MAX_TX_CH];
struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH];
u32 link; /* 1=link on, 0=link off */
@ -488,6 +488,9 @@ struct emac_priv {
struct mii_bus *mii_bus;
struct phy_device *phydev;
spinlock_t lock;
/*platform specific members*/
void (*int_enable) (void);
void (*int_disable) (void);
};
/* clock frequency for EMAC */
@ -495,11 +498,9 @@ static struct clk *emac_clk;
static unsigned long emac_bus_frequency;
static unsigned long mdio_max_freq;
/* EMAC internal utility function */
static inline u32 emac_virt_to_phys(void __iomem *addr)
{
return (u32 __force) io_v2p(addr);
}
#define emac_virt_to_phys(addr, priv) \
(((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \
+ priv->hw_ram_addr)
/* Cache macros - Packet buffers would be from skb pool which is cached */
#define EMAC_VIRT_NOCACHE(addr) (addr)
@ -1002,6 +1003,8 @@ static void emac_int_disable(struct emac_priv *priv)
emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0x0);
emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0x0);
/* NOTE: Rx Threshold and Misc interrupts are not disabled */
if (priv->int_disable)
priv->int_disable();
local_irq_restore(flags);
@ -1021,6 +1024,9 @@ static void emac_int_disable(struct emac_priv *priv)
static void emac_int_enable(struct emac_priv *priv)
{
if (priv->version == EMAC_VERSION_2) {
if (priv->int_enable)
priv->int_enable();
emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0xff);
emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0xff);
@ -1302,7 +1308,7 @@ static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
curr_bd = txch->active_queue_head;
if (NULL == curr_bd) {
emac_write(EMAC_TXCP(ch),
emac_virt_to_phys(txch->last_hw_bdprocessed));
emac_virt_to_phys(txch->last_hw_bdprocessed, priv));
txch->no_active_pkts++;
spin_unlock_irqrestore(&priv->tx_lock, flags);
return 0;
@ -1312,7 +1318,7 @@ static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
while ((curr_bd) &&
((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
(pkts_processed < budget)) {
emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd));
emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv));
txch->active_queue_head = curr_bd->next;
if (frame_status & EMAC_CPPI_EOQ_BIT) {
if (curr_bd->next) { /* misqueued packet */
@ -1399,7 +1405,7 @@ static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch)
txch->active_queue_tail = curr_bd;
if (1 != txch->queue_active) {
emac_write(EMAC_TXHDP(ch),
emac_virt_to_phys(curr_bd));
emac_virt_to_phys(curr_bd, priv));
txch->queue_active = 1;
}
++txch->queue_reinit;
@ -1411,10 +1417,11 @@ static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch)
tail_bd->next = curr_bd;
txch->active_queue_tail = curr_bd;
tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
tail_bd->h_next = (int)emac_virt_to_phys(curr_bd);
tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv);
frame_status = tail_bd->mode;
if (frame_status & EMAC_CPPI_EOQ_BIT) {
emac_write(EMAC_TXHDP(ch), emac_virt_to_phys(curr_bd));
emac_write(EMAC_TXHDP(ch),
emac_virt_to_phys(curr_bd, priv));
frame_status &= ~(EMAC_CPPI_EOQ_BIT);
tail_bd->mode = frame_status;
++txch->end_of_queue_add;
@ -1604,7 +1611,8 @@ static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param)
}
/* populate the hardware descriptor */
curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head);
curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head,
priv);
/* FIXME buff_ptr = dma_map_single(... data_ptr ...) */
curr_bd->buff_ptr = virt_to_phys(curr_bd->data_ptr);
curr_bd->off_b_len = rxch->buf_size;
@ -1879,7 +1887,7 @@ static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch,
rxch->active_queue_tail = curr_bd;
if (0 != rxch->queue_active) {
emac_write(EMAC_RXHDP(ch),
emac_virt_to_phys(rxch->active_queue_head));
emac_virt_to_phys(rxch->active_queue_head, priv));
rxch->queue_active = 1;
}
} else {
@ -1890,11 +1898,11 @@ static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch,
rxch->active_queue_tail = curr_bd;
tail_bd->next = curr_bd;
tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
tail_bd->h_next = emac_virt_to_phys(curr_bd);
tail_bd->h_next = emac_virt_to_phys(curr_bd, priv);
frame_status = tail_bd->mode;
if (frame_status & EMAC_CPPI_EOQ_BIT) {
emac_write(EMAC_RXHDP(ch),
emac_virt_to_phys(curr_bd));
emac_virt_to_phys(curr_bd, priv));
frame_status &= ~(EMAC_CPPI_EOQ_BIT);
tail_bd->mode = frame_status;
++rxch->end_of_queue_add;
@ -1987,7 +1995,7 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
curr_pkt->num_bufs = 1;
curr_pkt->pkt_length =
(frame_status & EMAC_RX_BD_PKT_LENGTH_MASK);
emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd));
emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv));
++rxch->processed_bd;
last_bd = curr_bd;
curr_bd = last_bd->next;
@ -1998,7 +2006,7 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
if (curr_bd) {
++rxch->mis_queued_packets;
emac_write(EMAC_RXHDP(ch),
emac_virt_to_phys(curr_bd));
emac_virt_to_phys(curr_bd, priv));
} else {
++rxch->end_of_queue;
rxch->queue_active = 0;
@ -2099,7 +2107,7 @@ static int emac_hw_enable(struct emac_priv *priv)
emac_write(EMAC_RXINTMASKSET, BIT(ch));
rxch->queue_active = 1;
emac_write(EMAC_RXHDP(ch),
emac_virt_to_phys(rxch->active_queue_head));
emac_virt_to_phys(rxch->active_queue_head, priv));
}
/* Enable MII */
@ -2660,6 +2668,9 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
priv->phy_mask = pdata->phy_mask;
priv->rmii_en = pdata->rmii_en;
priv->version = pdata->version;
priv->int_enable = pdata->interrupt_enable;
priv->int_disable = pdata->interrupt_disable;
emac_dev = &ndev->dev;
/* Get EMAC platform data */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -2692,6 +2703,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
priv->ctrl_ram_size = pdata->ctrl_ram_size;
priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset;
if (pdata->hw_ram_addr)
priv->hw_ram_addr = pdata->hw_ram_addr;
else
priv->hw_ram_addr = (u32 __force)res->start +
pdata->ctrl_ram_offset;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(emac_dev, "DaVinci EMAC: Error getting irq res\n");

View File

@ -8,8 +8,8 @@
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef _MACH_DAVINCI_EMAC_H
#define _MACH_DAVINCI_EMAC_H
#ifndef _LINUX_DAVINCI_EMAC_H
#define _LINUX_DAVINCI_EMAC_H
#include <linux/if_ether.h>
#include <linux/memory.h>
@ -19,12 +19,15 @@ struct emac_platform_data {
u32 ctrl_reg_offset;
u32 ctrl_mod_reg_offset;
u32 ctrl_ram_offset;
u32 hw_ram_addr;
u32 mdio_reg_offset;
u32 ctrl_ram_size;
u32 phy_mask;
u32 mdio_max_freq;
u8 rmii_en;
u8 version;
void (*interrupt_enable) (void);
void (*interrupt_disable) (void);
};
enum {