Hello.

Cyril Chemparathy wrote:

TNETV107X is a Texas Instruments SOC that shares a number of common features
with the Davinci architecture.  Some of the key differences between
traditional Davincis and this new SOC are as follow:

1. The SOCs clock architecture includes a new spread-spectrum PLL.  Some
elements of the clock architecture are reused from Davinci (e.g. LPSC), but
the PLL related code is overridden using existing interfaces in "struct clk".

2. The MMR layout on this SOC is substantially different from Davinci.
Consequently, the fixed I/O map is a whole lot more convoluted (more so than
DA8xx).  The net impact here is that IO_ADDRESS() will not work on this SoC,
and therefore all mappings have to be through ioremap().

3. The Davinci reset mechanism (via Timer64 watchdog) will not work on this
SoC.  This difference has not been addressed here (dummy davinci_wdt_device),
but a more "extensible" reset mechanism will need to be established
eventually.

4. The GPIO controller on this device is different.  Currently, this patch
leaves the traditional Davinci GPIO numbers (0..DAVINCI_N_GPIO) unused so that
the inline GPIO implementation can remain unmodified.  TNETV107X GPIOs are
exposed as higher numbered GPIOs, and are currently accessible only through
a non-inline version.

Signed-off-by: Cyril Chemparathy <[email protected]>

[...]

iff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index 0316e20..71f90f8 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -50,6 +50,11 @@ config ARCH_DAVINCI_DM365
        select AINTC
        select ARCH_DAVINCI_DMx
+config ARCH_DAVINCI_TNETV107X
+       select CPU_V6
+       select CP_INTC
+       bool "TNETV107X based system"
+
 comment "DaVinci Board Type"
config MACH_DAVINCI_EVM
@@ -173,6 +178,13 @@ config DA850_UI_RMII
endchoice +config MACH_TNETV107X
+       bool "TI TNETV107X Reference Platform"
+       default ARCH_DAVINCI_TNETV107X
+       depends on ARCH_DAVINCI_TNETV107X
+       help
+         Say Y here to select the TI TNETV107X Evaluation Module.
+
 config DAVINCI_MUX
        bool "DAVINCI multiplexing support"
        depends on ARCH_DAVINCI
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index 6aac880..ca01d56 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_DAVINCI_DM646x)       += dm646x.o devices.o
 obj-$(CONFIG_ARCH_DAVINCI_DM365)       += dm365.o devices.o
 obj-$(CONFIG_ARCH_DAVINCI_DA830)        += da830.o devices-da8xx.o
 obj-$(CONFIG_ARCH_DAVINCI_DA850)        += da850.o devices-da8xx.o
+obj-$(CONFIG_ARCH_DAVINCI_TNETV107X)    += tnetv107x.o devices-tnetv107x.o
obj-$(CONFIG_AINTC) += irq.o
 obj-$(CONFIG_CP_INTC)                  += cp_intc.o
@@ -30,6 +31,7 @@ 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
+obj-$(CONFIG_MACH_TNETV107X)           += board-tnetv107x-evm.o
# Power Management
 obj-$(CONFIG_CPU_FREQ)                 += cpufreq.o
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c 
b/arch/arm/mach-davinci/board-tnetv107x-evm.c
new file mode 100644
index 0000000..3704006
--- /dev/null
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -0,0 +1,270 @@

I think the EVM board code should be in a patch of its own, not collapsed into one big patch with the arch support code.

+static struct resource tnetv107x_evm_nand_resources[] = {
+       {
+               .start          = TNETV107X_ASYNC_EMIF_DATA_CE0_BASE,
+               .end            = TNETV107X_ASYNC_EMIF_DATA_CE0_BASE +
+                                       SZ_16M - 1,

  16 MiB window for NAND?

diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c 
b/arch/arm/mach-davinci/devices-tnetv107x.c
new file mode 100644
index 0000000..0d65ba6
--- /dev/null
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -0,0 +1,275 @@
+/*
+ * TI TNETV107X platform devices
+ *
+ * Author: Cyril Chemparathy <[email protected]>
+ *
+ * 2009 (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/init.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+
+#include <mach/common.h>
+#include <mach/irqs.h>
+#include <mach/edma.h>
+#include <mach/serial.h>
+#include <mach/tnetv107x.h>
+
+#include "clock.h"
+
+struct tnetv107x_gpio_regs {
+       u32     idver;
+       u32     data_in[3];
+       u32     data_out[3];
+       u32     direction[3];
+       u32     enable[3];
+};
+
+struct tnetv107x_gpio_controller {
+       struct tnetv107x_gpio_regs __iomem *regs;
+       struct gpio_chip        chip;
+};
+
+#define gpio_reg_index(gpio)   ((gpio) >> 5)
+#define gpio_reg_bit(gpio)     BIT((gpio) & 0x1f)
+
+#define gpio_reg_rmw(reg, mask, val)   \
+       __raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg))
+
+#define gpio_reg_set_bit(reg, gpio)    \
+       gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio))
+
+#define gpio_reg_clear_bit(reg, gpio)  \
+       gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0)
+
+#define gpio_reg_get_bit(reg, gpio)    \
+       (__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio))
+
+#define chip_to_gpio(chip)             \
+       container_of(chip, struct tnetv107x_gpio_controller, chip)
+
+static struct tnetv107x_gpio_controller tnetv107x_gpio_controller;

  Shouldn't the above be in gpio.c?

+static struct edma_soc_info edma_info[] = {
+       {
+               .n_channel              = 32,

  Wait, haven't you declared 64 DMA channels in patch 11/14?

+static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned gpio)
+{
+       struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       gpio_reg_set_bit(&ctlr->regs->enable, gpio);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned gpio)
+{
+       struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       gpio_reg_clear_bit(&ctlr->regs->enable, gpio);
+
+       local_irq_restore(flags);
+}
+
+static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned gpio)
+{
+       struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       gpio_reg_set_bit(&ctlr->regs->direction, gpio);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static int tnetv107x_gpio_dir_out(struct gpio_chip *chip,
+               unsigned gpio, int value)
+{
+       struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       if (value)
+               gpio_reg_set_bit(&ctlr->regs->data_out, gpio);
+       else
+               gpio_reg_clear_bit(&ctlr->regs->data_out, gpio);
+
+       gpio_reg_clear_bit(&ctlr->regs->direction, gpio);
+
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+       struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+       int ret;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       ret = gpio_reg_get_bit(&ctlr->regs->data_in, gpio);
+
+       local_irq_restore(flags);
+
+       return ret ? 1 : 0;
+}
+
+static void tnetv107x_gpio_set(struct gpio_chip *chip,
+               unsigned gpio, int value)
+{
+       struct tnetv107x_gpio_controller *ctlr = chip_to_gpio(chip);
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       if (value)
+               gpio_reg_set_bit(&ctlr->regs->data_out, gpio);
+       else
+               gpio_reg_clear_bit(&ctlr->regs->data_out, gpio);
+
+       local_irq_restore(flags);
+}
+
+static int __init tnetv107x_gpio_setup(void)
+{
+       struct tnetv107x_gpio_controller *ctlr = &tnetv107x_gpio_controller;
+
+       ctlr->regs = ioremap(TNETV107X_GPIO_BASE, PAGE_SIZE);
+
+       ctlr->chip.label             = "TNETV107X";
+       ctlr->chip.request           = tnetv107x_gpio_request;
+       ctlr->chip.free                      = tnetv107x_gpio_free;
+       ctlr->chip.direction_input   = tnetv107x_gpio_dir_in;
+       ctlr->chip.get                       = tnetv107x_gpio_get;
+       ctlr->chip.direction_output  = tnetv107x_gpio_dir_out;
+       ctlr->chip.set                       = tnetv107x_gpio_set;
+       ctlr->chip.base                      = TNETV107X_GPIO(0);
+       ctlr->chip.ngpio             = TNETV107X_N_GPIOS;
+       ctlr->chip.can_sleep         = 0;
+
+       gpiochip_add(&ctlr->chip);
+
+       return 0;
+}
+pure_initcall(tnetv107x_gpio_setup);

  I do think devices-*.c file is a bad place for GPIO code.

diff --git a/arch/arm/mach-davinci/include/mach/debug-macro.S 
b/arch/arm/mach-davinci/include/mach/debug-macro.S
index b8b47a4..35860af 100644
--- a/arch/arm/mach-davinci/include/mach/debug-macro.S
+++ b/arch/arm/mach-davinci/include/mach/debug-macro.S
@@ -32,6 +32,15 @@
 #define UART_VIRT      IO_ADDRESS(UART_PHYS)
 #endif
+#if defined(CONFIG_ARCH_DAVINCI_TNETV107X)

The UART address should be machine-, not arch-specific... you can have different UART used on non-EVM board.

+#include <mach/tnetv107x.h>
+#ifdef UART_PHYS
+#error "CONFIG_DEBUG_LL is incompatible with multiple archs"
+#endif
+#define UART_PHYS      TNETV107X_UART1_BASE
+#define UART_VIRT      TNETV107X_UART1_VIRT
+#endif
+
 #define UART_SHIFT     2
.macro addruart, rx, tmp

[...]

diff --git a/arch/arm/mach-davinci/tnetv107x.c 
b/arch/arm/mach-davinci/tnetv107x.c
new file mode 100644
index 0000000..d79092a
--- /dev/null
+++ b/arch/arm/mach-davinci/tnetv107x.c
@@ -0,0 +1,1215 @@

[...]

+/*
+ * TNETV107X platforms do not use the static mappings from Davinci
+ * IO_PHYS/IO_VIRT. This SOC's interesting MMRs are at different addresses,
+ * and changing IO_PHYS would break away from existing Davinci SOCs.
+ *
+ * The primary impact of the current model is that IO_ADDRESS() is not to be
+ * used to map registers on TNETV107X. With the exception of early boot code
+ * in tnetv107x_init() (where fixed maps are necessary), all other pieces of
+ * code absolutely _must_ use ioremap().
+ *
+ * In the following map, we reserve the top (highest address) 16K for mapping
+ * in interrupt controller registers. The remainder of the available space is
+ * mapped starting at physical address 0808:0000. All of the register areas
+ * accessed via fixed_ioremap() below must fall into one of these two
+ * segments.
+ */
+static struct map_desc tnetv107x_io_desc[] = {
+       {       /* EDMA */
+               .virtual        = IO_VIRT,
+               .pfn            = __phys_to_pfn(IO_PHYS),
+               .length         = SZ_1M,
+               .type           = MT_DEVICE
+       },
+       {       /* INTC */
+               .virtual        = IO_VIRT + SZ_1M,
+               .pfn            = __phys_to_pfn(TNETV107X_INTC_BASE),
+               .length         = SZ_1M,

  Whole megabyte for cp_intc?

+void __init tnetv107x_init(void)
+{
+       void __iomem *tmp;
+       int i;
+
+       /*
+        * Figure out virtual addresses for necessary peripherals, but do not
+        * access any of these here. iotable_init() needs to happen for the
+        * mappings to actually get setup
+        */
+       tmp = fixed_ioremap(TNETV107X_CLOCK_CONTROL_BASE, SZ_4K);
+       clk_ctrl_regs = tmp;

  Could be coded in one line...

+       for (i = 0; i < N_PLLS; i++) {
+               sspll_regs[i] = tmp + sspll_regs_base[i];
+               pllctl_regs[i] = tmp + pllctl_regs_base[i];
+       }
+
+       tmp = fixed_ioremap(TNETV107X_PSC_BASE, SZ_4K);
+       psc_regs[0] = tmp;

  Why use 'tmp' at all?

+       tmp = fixed_ioremap(TNETV107X_INTC_BASE, SZ_16K);
+       tnetv107x_soc_info.intc_base    = tmp;
+
+       tmp = fixed_ioremap(TNETV107X_TIMER0_BASE, 0x100);
+       tnetv107x_timer_instance[0].base = tmp;
+
+       tmp = fixed_ioremap(TNETV107X_TIMER1_BASE, 0x100);
+       tnetv107x_timer_instance[1].base = tmp;

  Same here...

WBR, Sergei

_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to