Commit 9d7fa5ee authored by Kevin Hilman's avatar Kevin Hilman

[PATCH] ARM: DaVinci: core support plus serial and ethernet

Signed-off-by: default avatarKevin Hilman <khilman@mvista.com>
parent 46c0c428
...@@ -270,6 +270,10 @@ config ARCH_AT91RM9200 ...@@ -270,6 +270,10 @@ config ARCH_AT91RM9200
Say Y here if you intend to run this kernel on an Atmel Say Y here if you intend to run this kernel on an Atmel
AT91RM9200-based board. AT91RM9200-based board.
config ARCH_DAVINCI
bool "TI DaVinci"
endchoice endchoice
source "arch/arm/mach-clps711x/Kconfig" source "arch/arm/mach-clps711x/Kconfig"
...@@ -314,6 +318,8 @@ source "arch/arm/mach-realview/Kconfig" ...@@ -314,6 +318,8 @@ source "arch/arm/mach-realview/Kconfig"
source "arch/arm/mach-at91rm9200/Kconfig" source "arch/arm/mach-at91rm9200/Kconfig"
source "arch/arm/mach-davinci/Kconfig"
# Definitions to make life easier # Definitions to make life easier
config ARCH_ACORN config ARCH_ACORN
bool bool
...@@ -525,7 +531,7 @@ config LEDS ...@@ -525,7 +531,7 @@ config LEDS
ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \ ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \
ARCH_AT91RM9200 ARCH_AT91RM9200 || ARCH_DAVINCI
help help
If you say Y here, the LEDs on your machine will be used If you say Y here, the LEDs on your machine will be used
to provide useful information about your current system status. to provide useful information about your current system status.
...@@ -538,7 +544,9 @@ config LEDS ...@@ -538,7 +544,9 @@ config LEDS
system, but the driver will do nothing. system, but the driver will do nothing.
config LEDS_TIMER config LEDS_TIMER
bool "Timer LED" if !ARCH_CDB89712 bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
MACH_OMAP_H2 || MACH_OMAP_PERSEUS2 || \
MACH_DAVINCI_EVM
depends on LEDS depends on LEDS
default y if ARCH_EBSA110 default y if ARCH_EBSA110
help help
...@@ -811,7 +819,7 @@ source "drivers/acorn/block/Kconfig" ...@@ -811,7 +819,7 @@ source "drivers/acorn/block/Kconfig"
if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \ if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \ || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \ || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
|| ARCH_IXP23XX || ARCH_IXP23XX || ARCH_DAVINCI
source "drivers/ide/Kconfig" source "drivers/ide/Kconfig"
endif endif
......
...@@ -116,6 +116,7 @@ endif ...@@ -116,6 +116,7 @@ endif
machine-$(CONFIG_ARCH_REALVIEW) := realview machine-$(CONFIG_ARCH_REALVIEW) := realview
machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200 machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200
machine-$(CONFIG_ARCH_EP93XX) := ep93xx machine-$(CONFIG_ARCH_EP93XX) := ep93xx
machine-$(CONFIG_ARCH_DAVINCI) := davinci
ifeq ($(CONFIG_ARCH_EBSA110),y) ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line. # This is what happens if you forget the IOCS16 line.
......
This diff is collapsed.
if ARCH_DAVINCI
menu "TI DaVinci Implementations"
comment "DaVinci Core Type"
config ARCH_DAVINCI644x
default y
bool "DaVinci 644x based system"
comment "DaVinci Board Type"
config MACH_DAVINCI_EVM
bool "TI DaVinci EVM"
default y
depends on ARCH_DAVINCI644x
help
Configure this option to specify the whether the board used
for development is a DaVinci EVM
config DAVINCI_I2C_EXPANDER
bool "TI DaVinci I2C Expander"
default y
depends on ARCH_DAVINCI644x
select I2C_DAVINCI
help
Configure this option to specify whether the board used
has I2C exapnder with ATA, USB, CF.
config DAVINCI_MCBSP
bool "DaVinci McBSP Driver"
depends on ARCH_DAVINCI
---help---
DaVinci McBSP driver. Auto-enabled by DaVinci sound driver.
comment "DaVinci Options"
config DAVINCI_BLK_DEV_CF
bool "TI DaVinci CF Card Support"
default Y
depends on BLK_DEV_DAVINCI
help
Configure this option to enable CF Card support.
endmenu
endif
#
# Makefile for the linux kernel.
#
#
# Common objects
obj-y := time.o irq.o dma.o clock.o serial.o
# Board specific
obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o i2c-emac.o
obj-$(CONFIG_DAVINCI_MCBSP) += mcbsp.o
obj-$(CONFIG_I2C_DAVINCI) += i2c-client.o
ifeq ($(CONFIG_LEDS),y)
obj-$(CONFIG_MACH_DAVINCI_EVM) += leds-evm.o
endif
zreladdr-y := 0x80008000
params_phys-y := 0x80000100
initrd_phys-y := 0x80800000
/*
* linux/arch/arm/mach-davinci/board-evm.c
*
* TI DaVinci EVM board
*
* Copyright (C) 2006 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.
* ----------------------------------------------------------------------------
*
*/
/**************************************************************************
* Included Files
**************************************************************************/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
#include <linux/usb_musb.h>
#endif
#include <asm/setup.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
#include <asm/arch/hardware.h>
#include "clock.h"
static void davinci_nop_release(struct device *dev)
{
/* Nothing */
}
/*
* USB
*/
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
static struct musb_hdrc_platform_data usb_data = {
#if defined(CONFIG_USB_MUSB_OTG)
/* OTG requires a Mini-AB connector */
.mode = MUSB_OTG,
#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
.mode = MUSB_PERIPHERAL,
#elif defined(CONFIG_USB_MUSB_HOST)
.mode = MUSB_HOST,
#endif
/* irlml6401 switches 5V */
.power = 255, /* sustains 3.0+ Amps (!) */
.potpgt = 4, /* ~8 msec */
/* REVISIT multipoint is a _chip_ capability; not board specific */
.multipoint = 1,
};
static struct resource usb_resources [] = {
{
/* physical address */
.start = DAVINCI_USB_OTG_BASE,
.end = DAVINCI_USB_OTG_BASE + 0x5ff,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_USBINT,
.flags = IORESOURCE_IRQ,
},
};
static u64 usb_dmamask = DMA_32BIT_MASK;
static struct platform_device usb_dev = {
.name = "musb_hdrc",
.id = -1,
.dev = {
.platform_data = &usb_data,
.dma_mask = &usb_dmamask,
.coherent_dma_mask = DMA_32BIT_MASK,
},
.resource = usb_resources,
.num_resources = ARRAY_SIZE(usb_resources),
};
static inline void setup_usb(void)
{
/* REVISIT: everything except platform_data setup should be
* shared between all DaVinci boards using the same core.
*/
int status;
status = platform_device_register(&usb_dev);
if (status != 0)
pr_debug("setup_usb --> %d\n", status);
else
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_USB, 1);
}
#else
static inline void setup_usb(void)
{
/* NOP */
}
#endif /* CONFIG_USB_MUSB_HDRC */
#ifdef CONFIG_I2C_DAVINCI
static struct resource i2c_resources[] = {
{
.start = IO_ADDRESS(DAVINCI_I2C_BASE),
.end = IO_ADDRESS(DAVINCI_I2C_BASE) + 0x40,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_I2C,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device davinci_i2c_device = {
.name = "i2c_davinci",
.id = 1,
.dev = {
.release = davinci_nop_release,
},
.num_resources = ARRAY_SIZE(i2c_resources),
.resource = i2c_resources,
};
static inline void setup_i2c(void)
{
(void) platform_device_register(&davinci_i2c_device);
}
#else
static inline void setup_i2c(void)
{
/* NOP */
}
#endif
static void board_init(void)
{
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1);
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1);
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1);
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1);
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1);
/* Turn on WatchDog timer LPSC. Needed for RESET to work */
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1);
}
/*
* DaVinci IO Mapping
*/
static struct map_desc davinci_io_desc[] __initdata = {
{
.virtual = IO_VIRT,
.pfn = __phys_to_pfn(IO_PHYS),
.length = IO_SIZE,
.type = MT_DEVICE
},
{
.virtual = DAVINCI_IRAM_VIRT,
.pfn = __phys_to_pfn(DAVINCI_IRAM_BASE),
.length = SZ_16K,
.type = MT_DEVICE
}
};
static void __init
davinci_map_io(void)
{
iotable_init(davinci_io_desc, ARRAY_SIZE(davinci_io_desc));
/* Initialize the DaVinci EVM board settigs */
board_init ();
}
static __init void evm_init(void)
{
setup_usb();
setup_i2c();
}
extern void davinci_irq_init(void);
extern struct sys_timer davinci_timer;
MACHINE_START(DAVINCI_EVM, "DaVinci EVM")
/* Maintainer: MontaVista Software <source@mvista.com> */
.phys_io = IO_PHYS,
.io_pg_offst = (io_p2v(IO_PHYS) >> 18) & 0xfffc,
.boot_params = (DAVINCI_DDR_BASE + 0x100),
.map_io = davinci_map_io,
.init_irq = davinci_irq_init,
.timer = &davinci_timer,
.init_machine = evm_init,
MACHINE_END
/*
* linux/arch/arm/mach-davinci/clock.c
*
* TI DaVinci clock config file
*
* Copyright (C) 2006 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.
* ----------------------------------------------------------------------------
*
*/
/**************************************************************************
* Included Files
**************************************************************************/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/clk.h>
#include <asm/setup.h>
#include <asm/semaphore.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/arch/hardware.h>
#include "clock.h"
#define DAVINCI_MAX_CLK 9
#define PLL1_PLLM __REG(0x01c40910)
#define PLL2_PLLM __REG(0x01c40D10)
#define PTCMD __REG(0x01C41120)
#define PDSTAT __REG(0x01C41200)
#define PDCTL1 __REG(0x01C41304)
#define EPCPR __REG(0x01C41070)
#define PTSTAT __REG(0x01C41128)
#define MDSTAT IO_ADDRESS(0x01C41800)
#define MDCTL IO_ADDRESS(0x01C41A00)
#define VDD3P3V_PWDN __REG(0x01C40048)
#define PINMUX0 __REG(0x01c40000)
#define PINMUX1 __REG(0x01c40004)
static LIST_HEAD(clocks);
static DECLARE_MUTEX(clocks_sem);
static DEFINE_SPINLOCK(clockfw_lock);
static unsigned int commonrate;
static unsigned int armrate;
static unsigned int fixedrate = 27000000; /* 27 MHZ */
/**************************************
Routine: board_setup_psc
Description: Enable/Disable a PSC domain
**************************************/
void board_setup_psc(unsigned int domain, unsigned int id, char enable)
{
volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id);
volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id);
if (enable) {
*mdctl |= 0x00000003; /* Enable Module */
} else {
*mdctl &= 0xFFFFFFF2; /* Disable Module */
}
if ((PDSTAT & 0x00000001) == 0) {
PDCTL1 |= 0x1;
PTCMD = (1 << domain);
while ((((EPCPR >> domain) & 1) == 0)) ;
PDCTL1 |= 0x100;
while (!(((PTSTAT >> domain) & 1) == 0)) ;
} else {
PTCMD = (1 << domain);
while (!(((PTSTAT >> domain) & 1) == 0)) ;
}
if (enable) {
while (!((*mdstat & 0x0000001F) == 0x3)) ;
} else {
while (!((*mdstat & 0x0000001F) == 0x2)) ;
}
}
static int board_setup_peripheral(unsigned int id)
{
switch (id) {
case DAVINCI_LPSC_ATA:
PINMUX0 |= (1 << 17) | (1 << 16);
break;
case DAVINCI_LPSC_MMC_SD:
/* VDD power manupulations are done in U-Boot for CPMAC
* so applies to MMC as well
*/
/*Set up the pull regiter for MMC */
VDD3P3V_PWDN = 0x0;
PINMUX1 &= (~(1 << 9));
break;
case DAVINCI_LPSC_I2C:
PINMUX1 |= (1 << 7);
break;
case DAVINCI_LPSC_McBSP:
PINMUX1 |= (1 << 10);
break;
default:
break;
}
}
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
down(&clocks_sem);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
up(&clocks_sem);
return clk;
}
EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
if (clk && !IS_ERR(clk))
module_put(clk->owner);
}
EXPORT_SYMBOL(clk_put);
int __clk_enable(struct clk *clk)
{
if (clk->flags & ALWAYS_ENABLED)
return 0;
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
return 0;
}
void __clk_disable(struct clk *clk)
{
if (clk->usecount)
return;
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
}
int clk_enable(struct clk *clk)
{
unsigned long flags;
int ret = 0;
if (clk->usecount++ == 0) {
spin_lock_irqsave(&clockfw_lock, flags);
ret = __clk_enable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
board_setup_peripheral(clk->lpsc);
}
return ret;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
unsigned long flags;
if (clk->usecount > 0 && !(--clk->usecount)) {
spin_lock_irqsave(&clockfw_lock, flags);
__clk_disable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
}
EXPORT_SYMBOL(clk_disable);
unsigned long clk_get_rate(struct clk *clk)
{
return *(clk->rate);
}
EXPORT_SYMBOL(clk_get_rate);
int clk_register(struct clk *clk)
{
down(&clocks_sem);
list_add(&clk->node, &clocks);
up(&clocks_sem);
return 0;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
down(&clocks_sem);
list_del(&clk->node);
up(&clocks_sem);
}
EXPORT_SYMBOL(clk_unregister);
static struct clk davinci_clks[DAVINCI_MAX_CLK] = {
{
.name = "ARMCLK",
.rate = &armrate,
.lpsc = -1,
.flags = ALWAYS_ENABLED,
},
{
.name = "UART",
.rate = &fixedrate,
.lpsc = DAVINCI_LPSC_UART0,
.usecount = 1,
},
{
.name = "EMACCLK",
.rate = &commonrate,
.lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
},
{
.name = "I2CCLK",
.rate = &fixedrate,
.lpsc = DAVINCI_LPSC_I2C,
},
{
.name = "IDECLK",
.rate = &commonrate,
.lpsc = DAVINCI_LPSC_ATA,
},
{
.name = "McBSPCLK",
.rate = &commonrate,
.lpsc = DAVINCI_LPSC_McBSP,
},
{
.name = "MMCSDCLK",
.rate = &commonrate,
.lpsc = DAVINCI_LPSC_MMC_SD,
},
{
.name = "SPICLK",
.rate = &commonrate,
.lpsc = DAVINCI_LPSC_SPI,
},
{
.name = "AEMIFCLK",
.rate = &commonrate,
.lpsc = DAVINCI_LPSC_AEMIF,
.usecount = 1,
}
};
static int davinci_clk_init(void)
{
struct clk *clkp;
int count = 0;
commonrate = ((PLL1_PLLM + 1) * 27000000) / 6;
armrate = ((PLL1_PLLM + 1) * 27000000) / 2;
for (clkp = davinci_clks; count < DAVINCI_MAX_CLK; count++, clkp++) {
clk_register(clkp);
/* Turn on clocks that have been enabled in the
* table above */
if (clkp->usecount) {
clk_enable(clkp);
}
}
return 0;
}
arch_initcall(davinci_clk_init);
/*
* linux/arch/arm/mach-davinci/clock.h
*
* BRIEF MODULE DESCRIPTION
* TI DAVINCI clock definitions
*
* Copyright (C) 2006 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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_CLOCK_H
#define __ARCH_ARM_DAVINCI_CLOCK_H
struct module;
struct clk {
struct list_head node;
struct module *owner;
const char *name;
unsigned int *rate;
__s8 usecount;
__u8 flags;
__u8 lpsc;
};
/* Clock flags */
#define RATE_CKCTL 1
#define RATE_FIXED 2
#define RATE_PROPAGATES 4
#define VIRTUAL_CLOCK 8
#define ALWAYS_ENABLED 16
#define ENABLE_REG_32BIT 32
int clk_register(struct clk *clk);
void clk_unregister(struct clk *clk);
int clk_init(void);
void board_setup_psc(unsigned int domain, unsigned int id, char enable);
#endif
This diff is collapsed.
/*
* linux/drivers/davinci/i2c-davinci-client.c
*
* Copyright (C) 2006 Texas Instruments Inc
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/clk.h>
#include <asm/semaphore.h>
#include <asm/arch/i2c-client.h>
static unsigned long initialized;
static struct semaphore expander_sema;
static struct i2c_client *client_handle;
/* This function is used for internal initialization */
int davinci_i2c_read(u8 size, u8 * val, u16 client_addr)
{
int err;
struct i2c_client *client = client_handle;
struct i2c_msg msg[1];
if (!client->adapter)
return -ENODEV;
msg->addr = client_addr;
msg->flags = I2C_M_RD;
msg->len = size;
msg->buf = val;
err = i2c_transfer(client->adapter, msg, 1);
if (err >= 0) {
return 0;
}
return err;
}
EXPORT_SYMBOL(davinci_i2c_read);
/* This function is used for internal initialization */
int davinci_i2c_write(u8 size, u8 * val, u16 client_addr)
{
int err;
struct i2c_client *client = client_handle;
struct i2c_msg msg[1];
if (!client->adapter)
return -ENODEV;
msg->addr = client_addr;
msg->flags = 0;
msg->len = size;
msg->buf = val;
err = i2c_transfer(client->adapter, msg, 1);
if (err >= 0)
return 0;
return err;
}
EXPORT_SYMBOL(davinci_i2c_write);
int davinci_i2c_expander_op(u16 client_addr, u35_expander_ops pin, u8 val)
{
int err = 0;
char cmd[4] = { 4, 6, 0x00, 0x09 };
u8 data_to_u35 = 0;
if (val > 1)
return -1;
down(&expander_sema);
err = davinci_i2c_read(1, &data_to_u35, 0x3A);
if (client_addr == 0x3A) {
switch (pin) {
case USB_DRVVBUS:
if (val)
data_to_u35 |= val;
else {
data_to_u35 &= (val | 0xFE);
}
break;
case VDDIMX_EN:
if (val)
data_to_u35 |= (val << 1);
else {
data_to_u35 &= (val | 0xFD);
}
break;
case VLYNQ_ON:
if (val)
data_to_u35 |= (val << 2);
else {
data_to_u35 &= (val | 0xFB);
}
break;
case CF_RESET:
if (val)
data_to_u35 |= (val << 3);
else {
data_to_u35 &= (val | 0xF7);
}
break;
case WLAN_RESET:
if (val)
data_to_u35 |= (val << 5);
else {
data_to_u35 &= (val | 0xDF);
}
break;
case ATA_SEL:
if (val)
data_to_u35 |= (val << 6);
else {
data_to_u35 &= (val | 0xBF);
}
break;
case CF_SEL:
davinci_i2c_write(4, cmd, 0x23);
if (val)
data_to_u35 |= (val << 7);
else {
data_to_u35 &= (val | 0x7F);
}
break;
default:
break;
}
} else {
printk("Only IO Expander at address 0x3A is suuported\n");
up(&expander_sema);
return -1;
}
err = davinci_i2c_write(1, &data_to_u35, 0x3A);
up(&expander_sema);
return err;
}
EXPORT_SYMBOL(davinci_i2c_expander_op);
static struct i2c_driver davinci_i2c_client_driver;
static int davinci_i2c_attach_client(struct i2c_adapter *adap, int addr)
{
struct i2c_client *client;
int err;
u8 data_to_u35 = 0xf6;
if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client_handle = client;
if (client->adapter)
return -EBUSY; /* our client is already attached */
client->addr = addr;
client->flags = 0;
client->driver = &davinci_i2c_client_driver;
client->adapter = adap;
strlcpy(client->name, "i2c_davinci_client", I2C_NAME_SIZE);
err = i2c_attach_client(client);
if (err) {
client->adapter = NULL;
goto exit_kfree;
}
err = davinci_i2c_write(1, &data_to_u35, 0x3A);
return 0;
exit_kfree:
kfree(client);
exit:
return err;
}
static int davinci_i2c_detach_client(struct i2c_client *client)
{
int err;
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
err = i2c_detach_client(client);
client->adapter = NULL;
return err;
}
static int davinci_i2c_probe_adapter(struct i2c_adapter *adap)
{
return davinci_i2c_attach_client(adap, 0x3A);
}
/* This is the driver that will be inserted */
static struct i2c_driver davinci_i2c_client_driver = {
.driver = {
.name = "davinci_i2c_client",
},
.attach_adapter = davinci_i2c_probe_adapter,
.detach_client = davinci_i2c_detach_client,
};
static int __init davinci_i2c_client_init(void)
{
return i2c_add_driver(&davinci_i2c_client_driver);
}
static void __exit davinci_i2c_client_exit(void)
{
i2c_del_driver(&davinci_i2c_client_driver);
}
module_init(davinci_i2c_client_init);
module_exit(davinci_i2c_client_exit);
/*
* <arch/arm/mach-davinci/i2c-emac.c
*
* Read MAC address from i2c-attached EEPROM
* FIXME: Move into network driver once stabilized
*
* Author: Texas Instruments
*
* 2006 (c) Texas Instruments, Inc. 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/module.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <asm/arch/i2c-client.h>
/* Get Ethernet address from kernel boot params */
static unsigned char cpmac_eth_string[20] = "deadbeaf";
/* This function gets the Ethernet MAC address from EEPROM
* Input buffer to be of atlease 20 bytes in length
*/
int davinci_get_macaddr (char *ptr)
{
#ifndef CONFIG_I2C_DAVINCI
printk(KERN_INFO "DaVinci EMAC: Unable to read MAC from EEPROM, "
"no i2c support in kernel.\n");
#else
char data[2] = { 0x7f, 0 };
char temp[20];
int i = 0;
if (ptr == NULL) {
return -EFAULT;
}
davinci_i2c_write (2, data, 0x50);
davinci_i2c_read (8, temp, 0x50);
/* check whether MAC address is available in ERPROM else try to
* to get it from bootparams for now. From Delta EVM MAC address
* should be available from I2C EEPROM.
*/
if ((temp [0] != 0xFF) |
(temp [1] != 0xFF) |
(temp [2] != 0xFF) |
(temp [3] != 0xFF) |
(temp [4] != 0xFF) |
(temp [5] != 0xFF) |
(temp [6] != 0xFF) )
{
ptr[0] = (*(temp+0) & 0xF0) >> 4;
ptr[1] = (*(temp+0) & 0x0F);
ptr[2] = ':';
ptr[3] = (*(temp+1) & 0xF0) >> 4;
ptr[4] = (*(temp+1) & 0x0F);
ptr[5] = ':';
ptr[6] = (*(temp+2) & 0xF0) >> 4;
ptr[7] = (*(temp+2) & 0x0F);
ptr[8] = ':';
ptr[9] = (*(temp+3) & 0xF0) >> 4;
ptr[10]= (*(temp+3) & 0x0F);
ptr[11]= ':';
ptr[12]= (*(temp+4) & 0xF0) >> 4;
ptr[13]= (*(temp+4) & 0x0F);
ptr[14]= ':';
ptr[15]= (*(temp+5) & 0xF0) >> 4;
ptr[16]= (*(temp+5) & 0x0F);
for (i = 0; i < 17; i++)
{
if (ptr[i] == ':')
continue;
else if (ptr[i] <= 9)
ptr[i] = ptr[i] + 48;
else
ptr[i] = ptr[i] + 87;
}
} else
#endif
{
strcpy (ptr, cpmac_eth_string);
}
return 0;
}
EXPORT_SYMBOL(davinci_get_macaddr);
static int davinci_cpmac_eth_setup(char *str)
{
/* The first char passed from the bootloader is '=', so ignore it */
strcpy(&cpmac_eth_string[0], &str[1]);
printk("TI DaVinci EMAC: Kernel Boot params Eth address: %s\n",
cpmac_eth_string);
return (1);
}
__setup("eth", davinci_cpmac_eth_setup);
/*
* linux/arch/arm/mach-davinci/irq.c
*
* TI DaVinci INTC config file
*
* Copyright (C) 2006 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/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
#include <asm/arch/irq.h>
#include <asm/arch/irqs.h>
#include <asm/arch/memory.h>
#include <asm/arch/hardware.h>
void intcInit(void);
#define INTNUM DAVINCI_MAXIRQNUM
#define EXCNUM ( 8 - 1 )
#define INTC_NUM_INTS_ONE_REGISTER 32
#define INTC_CLEAR_INTERRUPTS 0xFFFFFFFF
#define INTC_IDT_BASE DAVINCI_IRAM_VIRT
#define INTC_DISABLE_WHEN_CLEARED_MODE 0x4
#define INTC_IRQ_ENTRY_RAW 0x2
#define INTC_FIQ_ENTRY_RAW 0x1
#define INTC_VECT_OFFSET 0x100
volatile intc_registers *pintc = (intc_registers *) IO_ADDRESS(DAVINCI_ARM_INTC_BASE);
void davinci_intcinit(void);
/* Disable interrupt */
static void davinci_xdisable_int(unsigned int intno)
{
unsigned int mask;
if (intno < INTC_NUM_INTS_ONE_REGISTER) {
mask = 1 << intno;
pintc->eint0 &= ~mask;
} else if (intno <= INTNUM) {
mask = 1 << (intno - INTC_NUM_INTS_ONE_REGISTER);
pintc->eint1 &= ~mask;
}
}
/* Enable interrupt */
static void davinci_xenable_int(unsigned int intno)
{
unsigned int mask;
if (intno < INTC_NUM_INTS_ONE_REGISTER) {
mask = 1 << intno;
pintc->eint0 |= mask;
} else if (intno <= INTNUM) {
mask = 1 << (intno - INTC_NUM_INTS_ONE_REGISTER);
pintc->eint1 |= mask;
}
}
/* EOI interrupt */
void davinci_xeoi_pic(unsigned int intno)
{
unsigned int mask;
if (intno < INTC_NUM_INTS_ONE_REGISTER) {
mask = 1 << intno;
pintc->irq0 = mask;
} else if (intno < INTNUM) {
mask = 1 << (intno - INTC_NUM_INTS_ONE_REGISTER);
pintc->irq1 = mask;
}
}
static struct irqchip irqchip_0 = {
.ack = davinci_xeoi_pic,
.mask = davinci_xdisable_int,
.unmask = davinci_xenable_int,
};
void davinci_irq_init(void)
{
int i;
unsigned int *ptr = (unsigned int *)INTC_IDT_BASE;
davinci_intcinit();
ptr += INTC_VECT_OFFSET / (sizeof(*ptr));
for (i = 0; i < INTNUM; i++) {
if (i == 0) {
*ptr = 0xFFFFFFFF;
} else {
*ptr = i - 1;
}
ptr++;
}
/* Proggam the irqchip structures for ARM INTC */
for (i = 0; i < NR_IRQS; i++) {
if (i != IRQ_TINT1_TINT34)
set_irq_handler(i, do_edge_IRQ);
else
set_irq_handler(i, do_level_IRQ);
set_irq_chip(i, &irqchip_0);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
}
/* Interrupt Controller Initialize */
void davinci_intcinit(void)
{
/* Clear all interrupt requests - write 1 to clear the interrupt */
pintc->fiq0 = pintc->irq0 = INTC_CLEAR_INTERRUPTS;
pintc->fiq1 = pintc->irq1 = INTC_CLEAR_INTERRUPTS;
/* Disable all interrupts */
pintc->eint0 = pintc->eint1 = 0;
/* Interrupts disabled immediately. IRQ entry reflects all interrupts */
pintc->inctl = 0;
/* Set vector table base address
* last two bits are zero which means 4 byte entry */
pintc->eabase = (unsigned int)INTC_VECT_OFFSET;
/* Clear all interrupt requests - write 1 to clear the interrupt */
pintc->fiq0 = pintc->irq0 = INTC_CLEAR_INTERRUPTS;
pintc->fiq1 = pintc->irq1 = INTC_CLEAR_INTERRUPTS;
return;
}
/*
* <arch/arm/mach-davinci/leds-evm.c>
*
* LED support for TI DaVinci EVM
*
* 2006 (c) Texas Instruments, Inc. 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/config.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/errno.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/leds.h>
#include <asm/system.h>
/* eight leds on a pcf8574a I2C gpio expander; 0 == ON, 1 == OFF
* - drivers can use leds_event(led_{green,amber,red,blue}_{on,off})
* - userspace can do the same with /sys/devices/leds/leds0/event
*/
#define LED_DS8 (1 << 0)
#define LED_DS7 (1 << 1)
#define LED_DS6 (1 << 2)
#define LED_DS5 (1 << 3)
#define LED_DS4 (1 << 4)
#define LED_DS3 (1 << 5)
#define LED_DS2 (1 << 6)
#define LED_DS1 (1 << 7)
#define LED_STATE_ENABLED (1 << 8)
#define LED_STATE_CLAIMED (1 << 9)
static u16 hw_led_state;
static u8 leds_change;
/* these leds use I2C not GPIO, so we can't change values
* and remain "idle" ... so there's no "idle" LED.
*/
#define TIMER_LED LED_DS8
#define GREEN_LED LED_DS1
#define AMBER_LED LED_DS2
#define RED_LED LED_DS3
#define BLUE_LED LED_DS4
#define APP_LEDS (GREEN_LED | AMBER_LED | RED_LED | BLUE_LED)
static DEFINE_SPINLOCK(lock);
#define EVM_I2C_ADDR 0x38
#ifdef CONFIG_PREEMPT_RT
static void pcf_work(unsigned long unused)
#else
static void pcf_work(void *unused)
#endif
{
struct i2c_adapter *adap;
int err;
struct i2c_msg msg;
adap = i2c_get_adapter(0);
if (!adap)
return;
for (;;) {
static u8 leds;
spin_lock_irq(&lock);
leds = (u8) hw_led_state;
err= leds_change;
leds_change = 0;
spin_unlock_irq(&lock);
if (!err)
break;
msg.addr = EVM_I2C_ADDR;
msg.flags = 0;
msg.len = 1;
msg.buf = &leds;
err = i2c_transfer(adap, &msg, 1);
if (err < 0)
pr_debug("LED: set to %02x, err %d\n", leds, err);
}
}
/* Under PREEMPT_RT, this code may be called from the timer interrupt
* with is a real hard IRQ. Therefore, workqueues cannot be used
* because 'schedule_work()' can sleep. OTOH, for non-RT, tasklets
* cannot be used to call sleeping functions (such as i2c stack) */
#ifdef CONFIG_PREEMPT_RT
static DECLARE_TASKLET(work, pcf_work, 0);
#define doit() tasklet_schedule(&work)
#else
static DECLARE_WORK(work, pcf_work, NULL);
#define doit() schedule_work(&work)
#endif
static void evm_leds_event(led_event_t evt)
{
unsigned long flags;
u16 leds;
spin_lock_irqsave(&lock, flags);
if (!(hw_led_state & LED_STATE_ENABLED) && evt != led_start)
goto done;
leds = hw_led_state;
switch (evt) {
case led_start:
hw_led_state = LED_STATE_ENABLED | 0xff;
leds = 0;
break;
case led_halted:
case led_stop:
hw_led_state = 0xff;
// NOTE: work may still be pending!!
break;
case led_claim:
hw_led_state |= LED_STATE_CLAIMED;
hw_led_state |= APP_LEDS;
break;
case led_release:
hw_led_state &= ~LED_STATE_CLAIMED;
hw_led_state |= APP_LEDS;
break;
#ifdef CONFIG_LEDS_TIMER
case led_timer:
hw_led_state ^= TIMER_LED;
break;
#endif
/* actually all the LEDs are green */
case led_green_on:
if (leds & LED_STATE_CLAIMED)
hw_led_state &= ~GREEN_LED;
break;
case led_green_off:
if (leds & LED_STATE_CLAIMED)
hw_led_state |= GREEN_LED;
break;
case led_amber_on:
if (leds & LED_STATE_CLAIMED)
hw_led_state &= ~AMBER_LED;
break;
case led_amber_off:
if (leds & LED_STATE_CLAIMED)
hw_led_state |= AMBER_LED;
break;
case led_red_on:
if (leds & LED_STATE_CLAIMED)
hw_led_state &= ~RED_LED;
break;
case led_red_off:
if (leds & LED_STATE_CLAIMED)
hw_led_state |= RED_LED;
break;
case led_blue_on:
if (leds & LED_STATE_CLAIMED)
hw_led_state &= ~BLUE_LED;
break;
case led_blue_off:
if (leds & LED_STATE_CLAIMED)
hw_led_state |= BLUE_LED;
break;
default:
break;
}
leds ^= hw_led_state;
if (leds & 0xff) {
leds_change = (u8) leds;
doit();
}
done:
spin_unlock_irqrestore(&lock, flags);
}
static int __init evm_leds_init(void)
{
if (!machine_is_davinci_evm())
return 0;
leds_event = evm_leds_event;
leds_event(led_start);
return 0;
}
/* i2c is subsys_initcall, davinci i2c is device_initcall;
* this needs to follow both of them (sigh)
*/
late_initcall(evm_leds_init);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -121,8 +121,8 @@ config CPU_ARM925T ...@@ -121,8 +121,8 @@ config CPU_ARM925T
# ARM926T # ARM926T
config CPU_ARM926T config CPU_ARM926T
bool "Support ARM926T processor" bool "Support ARM926T processor"
depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_DAVINCI
default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_DAVINCI
select CPU_32v5 select CPU_32v5
select CPU_ABRT_EV5TJ select CPU_ABRT_EV5TJ
select CPU_CACHE_VIVT select CPU_CACHE_VIVT
......
...@@ -524,4 +524,9 @@ config I2C_OMAP ...@@ -524,4 +524,9 @@ config I2C_OMAP
help help
Support for TI OMAP I2C driver. Say yes if you want to use the OMAP Support for TI OMAP I2C driver. Say yes if you want to use the OMAP
I2C interface. I2C interface.
config I2C_DAVINCI
tristate "Davinci i2c driver"
depends on I2C && ARCH_DAVINCI
endmenu endmenu
...@@ -43,6 +43,7 @@ obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o ...@@ -43,6 +43,7 @@ obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
ifeq ($(CONFIG_I2C_DEBUG_BUS),y) ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
......
This diff is collapsed.
This diff is collapsed.
...@@ -819,6 +819,15 @@ config ULTRA32 ...@@ -819,6 +819,15 @@ config ULTRA32
<file:Documentation/networking/net-modules.txt>. The module <file:Documentation/networking/net-modules.txt>. The module
will be called smc-ultra32. will be called smc-ultra32.
config TI_DAVINCI_EMAC
tristate "TI DaVinci EMAC Support"
depends on NETDEVICES && MACH_DAVINCI_EVM
help
This driver supports TI's DaVinci Ethernet .
To compile this driver as a module, choose M here: the module
will be called ti_davinci_emac. This is recommended.
config SMC91X config SMC91X
tristate "SMC 91C9x/91C1xxx support" tristate "SMC 91C9x/91C1xxx support"
select CRC32 select CRC32
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment